protected virtual IDictionary <string, FacetGroup> GetFacets(CatalogSearchQuery searchQuery, int totalHits) { var result = new Dictionary <string, FacetGroup>(); var storeId = searchQuery.StoreId ?? _services.StoreContext.CurrentStore.Id; var languageId = searchQuery.LanguageId ?? _services.WorkContext.WorkingLanguage.Id; foreach (var key in searchQuery.FacetDescriptors.Keys) { var descriptor = searchQuery.FacetDescriptors[key]; var facets = new List <Facet>(); var kind = FacetGroup.GetKindByKey("Catalog", key); switch (kind) { case FacetGroupKind.Category: case FacetGroupKind.Brand: case FacetGroupKind.DeliveryTime: case FacetGroupKind.Rating: case FacetGroupKind.Price: if (totalHits == 0 && !descriptor.Values.Any(x => x.IsSelected)) { continue; } break; } if (kind == FacetGroupKind.Category) { var categoryTree = _categoryService.GetCategoryTree(0, false, storeId); var categories = categoryTree.Flatten(false); if (descriptor.MaxChoicesCount > 0) { categories = categories.Take(descriptor.MaxChoicesCount); } var nameQuery = _localizedPropertyRepository.TableUntracked .Where(x => x.LocaleKeyGroup == "Category" && x.LocaleKey == "Name" && x.LanguageId == languageId); var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue); foreach (var category in categories) { names.TryGetValue(category.Id, out var label); facets.Add(new Facet(new FacetValue(category.Id, IndexTypeCode.Int32) { IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(category.Id)), Label = label.HasValue() ? label : category.Name, DisplayOrder = category.DisplayOrder })); } } else if (kind == FacetGroupKind.Brand) { var manufacturers = _manufacturerService.GetAllManufacturers(null, storeId); if (descriptor.MaxChoicesCount > 0) { manufacturers = manufacturers.Take(descriptor.MaxChoicesCount).ToList(); } var nameQuery = _localizedPropertyRepository.TableUntracked .Where(x => x.LocaleKeyGroup == "Manufacturer" && x.LocaleKey == "Name" && x.LanguageId == languageId); var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue); foreach (var manu in manufacturers) { names.TryGetValue(manu.Id, out var label); facets.Add(new Facet(new FacetValue(manu.Id, IndexTypeCode.Int32) { IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(manu.Id)), Label = label.HasValue() ? label : manu.Name, DisplayOrder = manu.DisplayOrder })); } } else if (kind == FacetGroupKind.DeliveryTime) { var deliveryTimes = _deliveryTimeService.GetAllDeliveryTimes(); var nameQuery = _localizedPropertyRepository.TableUntracked .Where(x => x.LocaleKeyGroup == "DeliveryTime" && x.LocaleKey == "Name" && x.LanguageId == languageId); var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue); foreach (var deliveryTime in deliveryTimes) { if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount) { break; } names.TryGetValue(deliveryTime.Id, out var label); facets.Add(new Facet(new FacetValue(deliveryTime.Id, IndexTypeCode.Int32) { IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(deliveryTime.Id)), Label = label.HasValue() ? label : deliveryTime.Name, DisplayOrder = deliveryTime.DisplayOrder })); } } else if (kind == FacetGroupKind.Price) { var count = 0; var hasActivePredefinedFacet = false; var minPrice = _productRepository.Table.Where(x => x.Published && !x.Deleted && !x.IsSystemProduct).Min(x => (double)x.Price); var maxPrice = _productRepository.Table.Where(x => x.Published && !x.Deleted && !x.IsSystemProduct).Max(x => (double)x.Price); minPrice = FacetUtility.MakePriceEven(minPrice); maxPrice = FacetUtility.MakePriceEven(maxPrice); for (var i = 0; i < _priceThresholds.Length; ++i) { if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount) { break; } var price = _priceThresholds[i]; if (price < minPrice) { continue; } if (price >= maxPrice) { i = int.MaxValue - 1; } var selected = descriptor.Values.Any(x => x.IsSelected && x.Value == null && x.UpperValue != null && (double)x.UpperValue == price); if (selected) { hasActivePredefinedFacet = true; } facets.Add(new Facet(new FacetValue(null, price, IndexTypeCode.Double, false, true) { DisplayOrder = ++count, IsSelected = selected })); } // Add facet for custom price range. var priceDescriptorValue = descriptor.Values.FirstOrDefault(); var customPriceFacetValue = new FacetValue( priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.Value : null, priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.UpperValue : null, IndexTypeCode.Double, true, true); customPriceFacetValue.IsSelected = customPriceFacetValue.Value != null || customPriceFacetValue.UpperValue != null; if (!(totalHits == 0 && !customPriceFacetValue.IsSelected)) { facets.Insert(0, new Facet("custom", customPriceFacetValue)); } } else if (kind == FacetGroupKind.Rating) { foreach (var rating in FacetUtility.GetRatings()) { var newFacet = new Facet(rating); newFacet.Value.IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(rating.Value)); facets.Add(newFacet); } } else if (kind == FacetGroupKind.Availability || kind == FacetGroupKind.NewArrivals) { var value = descriptor.Values.FirstOrDefault(); if (value != null) { if (kind == FacetGroupKind.NewArrivals && totalHits == 0 && !value.IsSelected) { continue; } var newValue = value.Clone(); newValue.Value = true; newValue.TypeCode = IndexTypeCode.Boolean; newValue.IsRange = false; newValue.IsSelected = value.IsSelected; facets.Add(new Facet(newValue)); } } if (facets.Any(x => x.Published)) { //facets.Each(x => $"{key} {x.Value.ToString()}".Dump()); result.Add(key, new FacetGroup( "Catalog", key, descriptor.Label, descriptor.IsMultiSelect, false, descriptor.DisplayOrder, facets.OrderBy(descriptor))); } } return(result); }
protected virtual IDictionary <string, FacetGroup> GetFacets(CatalogSearchQuery searchQuery, int totalHits) { var result = new Dictionary <string, FacetGroup>(); var languageId = searchQuery.LanguageId ?? _services.WorkContext.WorkingLanguage.Id; foreach (var key in searchQuery.FacetDescriptors.Keys) { var descriptor = searchQuery.FacetDescriptors[key]; var facets = new List <Facet>(); var kind = FacetGroup.GetKindByKey(key); if (kind == FacetGroupKind.Category) { #region Category // order by product count var categoryQuery = from c in _categoryRepository.TableUntracked where !c.Deleted && c.Published join pc in _productCategoryRepository.TableUntracked on c.Id equals pc.CategoryId into pcm from pc in pcm.DefaultIfEmpty() group c by c.Id into grp orderby grp.Count() descending select new { Id = grp.FirstOrDefault().Id, Name = grp.FirstOrDefault().Name, DisplayOrder = grp.FirstOrDefault().DisplayOrder }; if (descriptor.MaxChoicesCount > 0) { categoryQuery = categoryQuery.Take(descriptor.MaxChoicesCount); } var categories = categoryQuery.ToList(); var nameQuery = _localizedPropertyRepository.TableUntracked .Where(x => x.LocaleKeyGroup == "Category" && x.LocaleKey == "Name" && x.LanguageId == languageId); var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue); foreach (var category in categories) { var selected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(category.Id)); if (totalHits == 0 && !selected) { continue; } string label = null; names.TryGetValue(category.Id, out label); facets.Add(new Facet(new FacetValue(category.Id, IndexTypeCode.Int32) { IsSelected = selected, Label = label.HasValue() ? label : category.Name, DisplayOrder = category.DisplayOrder })); } #endregion } else if (kind == FacetGroupKind.Brand) { #region Brand // order by product count var manufacturerQuery = from m in _manufacturerRepository.TableUntracked where !m.Deleted && m.Published join pm in _productManufacturerRepository.TableUntracked on m.Id equals pm.ManufacturerId into pmm from pm in pmm.DefaultIfEmpty() group m by m.Id into grp orderby grp.Count() descending select new { Id = grp.FirstOrDefault().Id, Name = grp.FirstOrDefault().Name, DisplayOrder = grp.FirstOrDefault().DisplayOrder }; if (descriptor.MaxChoicesCount > 0) { manufacturerQuery = manufacturerQuery.Take(descriptor.MaxChoicesCount); } var manufacturers = manufacturerQuery.ToList(); var nameQuery = _localizedPropertyRepository.TableUntracked .Where(x => x.LocaleKeyGroup == "Manufacturer" && x.LocaleKey == "Name" && x.LanguageId == languageId); var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue); foreach (var manu in manufacturers) { var selected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(manu.Id)); if (totalHits == 0 && !selected) { continue; } string label = null; names.TryGetValue(manu.Id, out label); facets.Add(new Facet(new FacetValue(manu.Id, IndexTypeCode.Int32) { IsSelected = selected, Label = label.HasValue() ? label : manu.Name, DisplayOrder = manu.DisplayOrder })); } #endregion } else if (kind == FacetGroupKind.DeliveryTime) { #region Delivery time var deliveryTimes = _deliveryTimeService.GetAllDeliveryTimes(); var nameQuery = _localizedPropertyRepository.TableUntracked .Where(x => x.LocaleKeyGroup == "DeliveryTime" && x.LocaleKey == "Name" && x.LanguageId == languageId); var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue); foreach (var deliveryTime in deliveryTimes) { if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount) { break; } var selected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(deliveryTime.Id)); if (totalHits == 0 && !selected) { continue; } string label = null; names.TryGetValue(deliveryTime.Id, out label); facets.Add(new Facet(new FacetValue(deliveryTime.Id, IndexTypeCode.Int32) { IsSelected = selected, Label = label.HasValue() ? label : deliveryTime.Name, DisplayOrder = deliveryTime.DisplayOrder })); } #endregion } else if (kind == FacetGroupKind.Price) { #region Price var count = 0; var hasActivePredefinedFacet = false; var minPrice = _productRepository.Table.Where(x => !x.Deleted && x.Published).Min(x => (double)x.Price); var maxPrice = _productRepository.Table.Where(x => !x.Deleted && x.Published).Max(x => (double)x.Price); minPrice = FacetUtility.MakePriceEven(minPrice); maxPrice = FacetUtility.MakePriceEven(maxPrice); for (var i = 0; i < _priceThresholds.Length; ++i) { if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount) { break; } var price = _priceThresholds[i]; if (price < minPrice) { continue; } if (price >= maxPrice) { i = int.MaxValue - 1; } var selected = descriptor.Values.Any(x => x.IsSelected && x.Value == null && x.UpperValue != null && (double)x.UpperValue == price); if (totalHits == 0 && !selected) { continue; } if (selected) { hasActivePredefinedFacet = true; } facets.Add(new Facet(new FacetValue(null, price, IndexTypeCode.Double, false, true) { DisplayOrder = ++count, IsSelected = selected })); } // Add facet for custom price range. var priceDescriptorValue = descriptor.Values.FirstOrDefault(); var customPriceFacetValue = new FacetValue( priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.Value : null, priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.UpperValue : null, IndexTypeCode.Double, true, true); customPriceFacetValue.IsSelected = customPriceFacetValue.Value != null || customPriceFacetValue.UpperValue != null; if (!(totalHits == 0 && !customPriceFacetValue.IsSelected)) { facets.Insert(0, new Facet("custom", customPriceFacetValue)); } #endregion } else if (kind == FacetGroupKind.Rating) { if (totalHits == 0 && !descriptor.Values.Any(x => x.IsSelected)) { continue; } foreach (var rating in FacetUtility.GetRatings()) { var newFacet = new Facet(rating); newFacet.Value.IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(rating.Value)); facets.Add(newFacet); } } else if (kind == FacetGroupKind.Availability || kind == FacetGroupKind.NewArrivals) { var value = descriptor.Values.FirstOrDefault(); if (value != null && !(totalHits == 0 && !value.IsSelected)) { var newValue = value.Clone(); newValue.Value = true; newValue.TypeCode = IndexTypeCode.Boolean; newValue.IsRange = false; newValue.IsSelected = value.IsSelected; facets.Add(new Facet(newValue)); } } if (facets.Any(x => x.Published)) { //facets.Each(x => $"{key} {x.Value.ToString()}".Dump()); result.Add(key, new FacetGroup( key, descriptor.Label, descriptor.IsMultiSelect, descriptor.DisplayOrder, facets.OrderBy(descriptor))); } } return(result); }