We are using Commerce 12 with Find. However, my question is less technical and more about best practices.
I'm struggling a little bit with the proper approach to searching a catalog. Our catalog has a fairly straightforward structure in which our products have high level properties (brand, flavor, texture) and our variants have container information (container type, size) that act as our SKUs.
The search results we would like to return are not products. We really want just the variants to show up in a product search. While I can do this by specifying the ClassType in the criteria object, we lose facets at the product level (such as brand).
As a general approach, what is the proper way to tackle a scenario like this? Do we have to do custom indexing or is there a more straightforward approach we could take? If we index, should we be adding product information to our variant entries or vise-versa?
I'm not sure I see the whole picture, but do you support searching by container information (i.e. SKU information), or only high level properties?
Easiest way would be to use an extension method to add container type and size to the products. It can just be a unique select on varitions size and variations container. The result would be IEumerable<string>
SearchClient.Instance.Conventions.ForInstancesOf<ProductContent>().IncludeField(_ => _.Sizes());
SearchClient.Instance.Conventions.ForInstancesOf<ProductContent>().IncludeField(_ => _.Containers());
public static class ProductContentExtensions
private static readonly Lazy<IRelationRepository> RelationRepository = new Lazy<IRelationRepository>(() => ServiceLocator.Current.GetInstance<IRelationRepository>());
private static readonly Lazy<IContentLoader> ContentLoader = new Lazy<IContentLoader>(() => ServiceLocator.Current.GetInstance<IContentLoader>());
public static IEnumerable<string> Sizes(this EntryContentBase productContent)
.Select(_ => _.Size);
public static IEnumerable<string> Containers(this EntryContentBase productContent)
.Select(_ => _.Container);
public static IEnumerable<VariationContent> VariationContents(this ProductContent productContent)
return ContentLoader.Value.GetItems(productContent.GetVariants(RelationRepository.Value), productContent.Language).OfType<VariationContent>();
Thanks Mark. I'm going to give this a shot this morning and see if this solves my issue. Since we actually want the search results to be SKUs in our case, I suspect I will want to use the same approach but on variants instead. Either way I can follow what you are suggesting.
Quan, we do support searching by SKU information. Our site has an auto-complete search that targets products as well as a more comprehensive search page that returns SKUs and makes use of facets. It was this second search that was giving me issues because the facets are tied to product properties that were not included in the index for SKU items.
Then I second Mark's suggestion
To close this one out, we followed Mark's suggestion and only altered it slightly to get product properties indexed within the SKU items.
To do this we added a method to retrieve the first parent product item as we always have just a single parent associated with a SKU.
public static ProductContent ParentProduct(this VariationContent variationContent)
var productContents = ContentLoader.Value
return productContents.Any() ? productContents.First() : null;
Then used this method in the individual property extensions like so:
public static string Brand(this VariationContent variationContent)
Works like a charm - Thanks!