On my product definition I have some properties that are set as "Use in Faceted search", and I'm using the example code on the uCommerce site to get products like this:
var products = SearchLibrary.GetProductsFor(category, facets);
This works great and the correct number of products are being returned, however I've noticed an issue where the Prices displayed in my list of facets are not based on Products but on Product Variants. I have 2 products, the first with 2 variants, the second with 4 variants. When I use the code below the Facet for prices has a hit count of 6:
SearchLibrary.GetFacetsFor(category, facets)
Is there a way of customizing the query to not return hits that are variants? I've tried this but I get no results:
var topLevelProductsOnly =
SearchLibrary.FacetedQuery().Where(x => x.Variants.Any()).ToList();
The reason you're not getting any results from the query you mention is that the field is not included in the default facet index. I have changed the default index to include this field going forward.
Meanwhile, you can fix this by changing the SaveLanguage pipeline (this is where the index is created and recreated when necessary) to include the Variants value.
The task replaces the existing one by registering it in Custom.config using component id "Language.CreateIndex":
public class CreateIndexTask : IPipelineTask<Infrastructure.Globalization.Language>
{
private readonly IRavenDbStoreProvider _storeProvider;
private readonly IRepository<PriceGroup> _priceGroupRepository;
public CreateIndexTask(IRavenDbStoreProvider storeProvider, IRepository<PriceGroup> priceGroupRepository)
{
_storeProvider = storeProvider;
_priceGroupRepository = priceGroupRepository;
}
public PipelineExecutionResult Execute(Infrastructure.Globalization.Language subject)
{
var store = _storeProvider.GetStore();
// Uses the display name of fields to create dynamic fields
// and the display names of data type pre values to create field value.
// If name or pre value doesn't have a language specific value it
// uses the values as stored on product document.
string indexDefinition = @"docs.Products.Select(product => new {
product.ProductDefinition,
product.ThumbnailImageUrl,
product.PrimaryImageUrl,
product.Sku,
product.VariantSku,
product.Name,
product.DisplayOnSite,
product.Weight,
product.AllowOrdering,
product.ModifiedBy,
product.ModifiedOn,
product.CreatedOn,
product.CreatedBy,
product.Variants,
Rating = this.Recurse(product, x => x.Variants).Select(x => new[] {x.Rating}),
product.CategoryIds,
_ = this.Recurse(product, x => x.Variants).Select(x => x.Properties.Select(y => y.Value.Select(z => (z.Value is string ? (IEnumerable<object>) new [] { z.Value } : (IEnumerable<object>) z.Value).Select(v => this.CreateField(LoadDocument(product.ProductDefinition).Fields.SingleOrDefault(field => field.Name == z.Key).Properties[""{CULTURECODE}""][""DisplayName""] ?? z.Key, LoadDocument(LoadDocument(product.ProductDefinition).Fields.SingleOrDefault(field => field.Name == z.Key).DataTypeId).PreValues.SingleOrDefault(preValue => preValue.Value == v).Properties[""{CULTURECODE}""][""DisplayName""] ?? v))))),
__ = this.Recurse(product, x => x.Variants).Select(x => x.Prices.Select(y => this.CreateField(y.Key, y.Value)))
})".Replace("{CULTURECODE}", subject.CultureCode); // string.Format doesn't work with @literals
string indexName = "Products/ByPropertyRecurse/{0}".FormatWith(subject.CultureCode);
store.DatabaseCommands.DeleteIndex(indexName);
var index = new IndexDefinition()
{
Map = indexDefinition,
Analyzers =
{
{"__all_fields", "KeywordAnalyzer"}
}
};
foreach (var priceGroup in _priceGroupRepository.Select(x => !x.Deleted))
{
index.SortOptions.Add(priceGroup.Name, SortOptions.Double);
}
store.DatabaseCommands.PutIndex(indexName, index);
return PipelineExecutionResult.Success;
}
}
Thanks for that code, I've added it and I now only get the expected 2 products and not the variants using this code:
var topLevelProductsOnly =
SearchLibrary.FacetedQuery().Where(x => x.Variants.Any()).ToList();
I'm trying to use the ToFacets() to only get Facets matching these 2 products, however the below code returns a list of Facets that include the Price Facet that has a Hit count of 6, not 2 which is including the Variant prices. Am I correct in thinking this should only return Facet values based on the LINQ query, or is there something extra I need to do here?
var topLevelProductsOnlyWithFacets =
SearchLibrary.FacetedQuery().Where(x => x.Variants.Any()).ToFacets().ToList();
I think for this my issue is more to do with unexpected values being returned and not filtering.
The Price facet returned in the below method call has 6 hits which looks as if it is including the variant prices.
var topLevelProductsOnlyWithFacets =
SearchLibrary.FacetedQuery()
.Where(x => x.CategoryIds.Any(y => y == categoryInt) && x.Variants.Any()).ToFacets()
.ToList();
There are 2 products and 6 variants of these products, which explains the 6 hits for the price facet. However as I'm including the x.Variants.Any() LINQ clause i was expecting these to be filtered out. Is there a way to exclude variant prices from the values returned?
Exclude varient prices from Facets
On my product definition I have some properties that are set as "Use in Faceted search", and I'm using the example code on the uCommerce site to get products like this:
This works great and the correct number of products are being returned, however I've noticed an issue where the Prices displayed in my list of facets are not based on Products but on Product Variants. I have 2 products, the first with 2 variants, the second with 4 variants. When I use the code below the Facet for prices has a hit count of 6:
SearchLibrary.GetFacetsFor(category, facets)
Is there a way of customizing the query to not return hits that are variants? I've tried this but I get no results:
Hi Chris,
The reason you're not getting any results from the query you mention is that the field is not included in the default facet index. I have changed the default index to include this field going forward.
Meanwhile, you can fix this by changing the SaveLanguage pipeline (this is where the index is created and recreated when necessary) to include the Variants value.
The task replaces the existing one by registering it in Custom.config using component id "Language.CreateIndex":
And the implementation to include the new field:
Hi Soren,
Thanks for that code, I've added it and I now only get the expected 2 products and not the variants using this code:
I'm trying to use the ToFacets() to only get Facets matching these 2 products, however the below code returns a list of Facets that include the Price Facet that has a Hit count of 6, not 2 which is including the Variant prices. Am I correct in thinking this should only return Facet values based on the LINQ query, or is there something extra I need to do here?
Thanks
Chris
Please refer to answer in this topic on how to filter the returned facets.
https://our.umbraco.org/projects/website-utilities/ucommerce/ucommerce-support/65289-Price-facet-returns
Hi Soren,
I think for this my issue is more to do with unexpected values being returned and not filtering.
The Price facet returned in the below method call has 6 hits which looks as if it is including the variant prices.
There are 2 products and 6 variants of these products, which explains the 6 hits for the price facet. However as I'm including the x.Variants.Any() LINQ clause i was expecting these to be filtered out. Is there a way to exclude variant prices from the values returned?
Thanks
is working on a reply...