protected virtual IDictionary<string, string> GetCommonFacetAliasByGroupKindMappings() { return _cacheManager.Get(ALL_FORUM_COMMONFACET_ALIAS_BY_KIND_KEY, () => { var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); var groupKinds = new FacetGroupKind[] { FacetGroupKind.Forum, FacetGroupKind.Customer, FacetGroupKind.Date }; foreach (var language in _languageService.GetAllLanguages()) { foreach (var groupKind in groupKinds) { var key = FacetUtility.GetFacetAliasSettingKey(groupKind, language.Id, "Forum"); var value = _settingService.GetSettingByKey<string>(key); if (value.HasValue()) { result.Add(key, value); } } } return result; }); }
protected virtual IDictionary <string, string> GetCommonFacetAliasByGroupKindMappings() { return(_cacheManager.Get(ALL_COMMONFACET_ALIAS_BY_KIND_KEY, () => { var result = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var groupKinds = new FacetGroupKind[] { FacetGroupKind.Category, FacetGroupKind.Brand, FacetGroupKind.Price, FacetGroupKind.Rating, FacetGroupKind.DeliveryTime, FacetGroupKind.Availability, FacetGroupKind.NewArrivals }; foreach (var language in _languageService.GetAllLanguages()) { foreach (var groupKind in groupKinds) { var key = FacetUtility.GetFacetAliasSettingKey(groupKind, language.Id); var value = _settingService.GetSettingByKey <string>(key); if (value.HasValue()) { result.Add(key, value); } } } return result; })); }
private void AddFacet( ForumSearchQuery query, FacetGroupKind kind, bool isMultiSelect, FacetSorting sorting, Action <FacetDescriptor> addValues) { string fieldName; var displayOrder = 0; switch (kind) { case FacetGroupKind.Forum: if (_searchSettings.ForumDisabled) { return; } fieldName = "forumid"; displayOrder = _searchSettings.ForumDisplayOrder; break; case FacetGroupKind.Customer: if (_searchSettings.CustomerDisabled) { return; } fieldName = "customerid"; displayOrder = _searchSettings.CustomerDisplayOrder; break; case FacetGroupKind.Date: if (_searchSettings.DateDisabled) { return; } fieldName = "createdon"; displayOrder = _searchSettings.DateDisplayOrder; break; default: throw new SmartException($"Unknown field name for facet group '{kind.ToString()}'"); } var descriptor = new FacetDescriptor(fieldName); descriptor.Label = _services.Localization.GetResource(FacetUtility.GetLabelResourceKey(kind) ?? kind.ToString()); descriptor.IsMultiSelect = isMultiSelect; descriptor.DisplayOrder = displayOrder; descriptor.OrderBy = sorting; descriptor.MinHitCount = _searchSettings.FilterMinHitCount; descriptor.MaxChoicesCount = _searchSettings.FilterMaxChoicesCount; addValues(descriptor); query.WithFacet(descriptor); }
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); }
protected override async Task <IEnumerable <RuleDescriptor> > LoadDescriptorsAsync() { var language = _services.WorkContext.WorkingLanguage; var currency = _services.WorkContext.WorkingCurrency; var oneStarStr = T("Search.Facet.1StarAndMore").Value; var xStarsStr = T("Search.Facet.XStarsAndMore").Value; var stores = _services.StoreContext.GetAllStores() .Select(x => new RuleValueSelectListOption { Value = x.Id.ToString(), Text = x.Name }) .ToArray(); var visibilities = await((ProductVisibility[])Enum.GetValues(typeof(ProductVisibility))) .SelectAsync(async x => new RuleValueSelectListOption { Value = ((int)x).ToString(), Text = await _localizationService.GetLocalizedEnumAsync(x) }) .ToArrayAsync(); var productTypes = await((ProductType[])Enum.GetValues(typeof(ProductType))) .SelectAsync(async x => new RuleValueSelectListOption { Value = ((int)x).ToString(), Text = await _localizationService.GetLocalizedEnumAsync(x) }) .ToArrayAsync(); var ratings = FacetUtility.GetRatings() .Reverse() .Skip(1) .Select(x => new RuleValueSelectListOption { Value = ((double)x.Value).ToString(CultureInfo.InvariantCulture), Text = (double)x.Value == 1 ? oneStarStr : xStarsStr.FormatInvariant(x.Value) }) .ToArray(); var categoryTree = _catalogSettings.ShowProductsFromSubcategories ? await _categoryService.GetCategoryTreeAsync(includeHidden : true) : null; #region Special filters CatalogSearchQuery categoryFilter(SearchFilterContext ctx, int[] x) { if (x?.Any() ?? false) { var ids = new HashSet <int>(x); if (_catalogSettings.ShowProductsFromSubcategories) { foreach (var id in x) { var node = categoryTree.SelectNodeById(id); if (node != null) { ids.AddRange(node.Flatten(false).Select(y => y.Id)); } } } return(ctx.Query.WithCategoryIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? (bool?)null : false, ids.ToArray())); } return(ctx.Query); }; CatalogSearchQuery stockQuantityFilter(SearchFilterContext ctx, int x) { if (ctx.Expression.Operator == RuleOperator.IsEqualTo || ctx.Expression.Operator == RuleOperator.IsNotEqualTo) { return(ctx.Query.WithStockQuantity(x, x, ctx.Expression.Operator == RuleOperator.IsEqualTo, ctx.Expression.Operator == RuleOperator.IsEqualTo)); } else if (ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo || ctx.Expression.Operator == RuleOperator.GreaterThan) { return(ctx.Query.WithStockQuantity(x, null, ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo, null)); } else if (ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo || ctx.Expression.Operator == RuleOperator.LessThan) { return(ctx.Query.WithStockQuantity(null, x, null, ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo)); } return(ctx.Query); }; CatalogSearchQuery priceFilter(SearchFilterContext ctx, decimal x) { var price = new Money(x, currency); if (ctx.Expression.Operator == RuleOperator.IsEqualTo || ctx.Expression.Operator == RuleOperator.IsNotEqualTo) { return(ctx.Query.PriceBetween(price, price, ctx.Expression.Operator == RuleOperator.IsEqualTo, ctx.Expression.Operator == RuleOperator.IsEqualTo)); } else if (ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo || ctx.Expression.Operator == RuleOperator.GreaterThan) { return(ctx.Query.PriceBetween(price, null, ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo, null)); } else if (ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo || ctx.Expression.Operator == RuleOperator.LessThan) { return(ctx.Query.PriceBetween(null, price, null, ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo)); } return(ctx.Query); }; CatalogSearchQuery createdFilter(SearchFilterContext ctx, DateTime x) { if (ctx.Expression.Operator == RuleOperator.IsEqualTo || ctx.Expression.Operator == RuleOperator.IsNotEqualTo) { return(ctx.Query.CreatedBetween(x, x, ctx.Expression.Operator == RuleOperator.IsEqualTo, ctx.Expression.Operator == RuleOperator.IsEqualTo)); } else if (ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo || ctx.Expression.Operator == RuleOperator.GreaterThan) { return(ctx.Query.CreatedBetween(x, null, ctx.Expression.Operator == RuleOperator.GreaterThanOrEqualTo, null)); } else if (ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo || ctx.Expression.Operator == RuleOperator.LessThan) { return(ctx.Query.CreatedBetween(null, x, null, ctx.Expression.Operator == RuleOperator.LessThanOrEqualTo)); } return(ctx.Query); }; #endregion var descriptors = new List <SearchFilterDescriptor> { new SearchFilterDescriptor <int>((ctx, x) => ctx.Query.HasStoreId(x)) { Name = "Store", DisplayName = T("Admin.Rules.FilterDescriptor.Store"), RuleType = RuleType.Int, SelectList = new LocalRuleValueSelectList(stores), Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.AllowedCustomerRoles(x)) { Name = "CustomerRole", DisplayName = T("Admin.Rules.FilterDescriptor.IsInCustomerRole"), RuleType = RuleType.IntArray, SelectList = new RemoteRuleValueSelectList("CustomerRole") { Multiple = true }, Operators = new RuleOperator[] { RuleOperator.In } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.PublishedOnly(x)) { Name = "Published", DisplayName = T("Admin.Catalog.Products.Fields.Published"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.AvailableOnly(x)) { Name = "AvailableByStock", DisplayName = T("Products.Availability.InStock"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.AvailableByDate(x)) { Name = "AvailableByDate", DisplayName = T("Admin.Rules.FilterDescriptor.AvailableByDate"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <int>((ctx, x) => ctx.Query.WithVisibility((ProductVisibility)x)) { Name = "Visibility", DisplayName = T("Admin.Catalog.Products.Fields.Visibility"), RuleType = RuleType.Int, SelectList = new LocalRuleValueSelectList(visibilities), Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithProductIds(x)) { Name = "Product", DisplayName = T("Common.Entity.Product"), RuleType = RuleType.IntArray, SelectList = new RemoteRuleValueSelectList("Product") { Multiple = true }, Operators = new RuleOperator[] { RuleOperator.In } }, new SearchFilterDescriptor <int>((ctx, x) => ctx.Query.IsProductType((ProductType)x)) { Name = "ProductType", DisplayName = T("Admin.Catalog.Products.Fields.ProductType"), RuleType = RuleType.Int, SelectList = new LocalRuleValueSelectList(productTypes), Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <int[]>(categoryFilter) { Name = "Category", DisplayName = T("Common.Entity.Category"), RuleType = RuleType.IntArray, SelectList = new RemoteRuleValueSelectList("Category") { Multiple = true }, Operators = new RuleOperator[] { RuleOperator.In } }, new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithManufacturerIds(null, x)) { Name = "Manufacturer", DisplayName = T("Common.Entity.Manufacturer"), RuleType = RuleType.IntArray, SelectList = new RemoteRuleValueSelectList("Manufacturer") { Multiple = true }, Operators = new RuleOperator[] { RuleOperator.In } }, // Same logic as the filter above product list. new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HasAnyCategory(!x)) { Name = "WithoutCategory", DisplayName = T("Admin.Catalog.Products.List.SearchWithoutCategories"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HasAnyManufacturer(!x)) { Name = "WithoutManufacturer", DisplayName = T("Admin.Catalog.Products.List.SearchWithoutManufacturers"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithProductTagIds(x)) { Name = "ProductTag", DisplayName = T("Admin.Catalog.Products.Fields.ProductTags"), RuleType = RuleType.IntArray, SelectList = new RemoteRuleValueSelectList("ProductTag") { Multiple = true }, Operators = new RuleOperator[] { RuleOperator.In } }, new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithDeliveryTimeIds(x)) { Name = "DeliveryTime", DisplayName = T("Admin.Catalog.Products.Fields.DeliveryTime"), RuleType = RuleType.IntArray, Operators = new RuleOperator[] { RuleOperator.In }, SelectList = new RemoteRuleValueSelectList("DeliveryTime") { Multiple = true } }, new SearchFilterDescriptor <int>(stockQuantityFilter) { Name = "StockQuantity", DisplayName = T("Admin.Catalog.Products.Fields.StockQuantity"), RuleType = RuleType.Int }, new SearchFilterDescriptor <decimal>(priceFilter) { Name = "Price", DisplayName = T("Admin.Catalog.Products.Fields.Price"), RuleType = RuleType.Money }, new SearchFilterDescriptor <DateTime>(createdFilter) { Name = "CreatedOn", DisplayName = T("Common.CreatedOn"), RuleType = RuleType.DateTime }, new SearchFilterDescriptor <double>((ctx, x) => ctx.Query.WithRating(x, null)) { Name = "Rating", DisplayName = T("Admin.Catalog.ProductReviews.Fields.Rating"), RuleType = RuleType.Float, Operators = new RuleOperator[] { RuleOperator.GreaterThanOrEqualTo }, SelectList = new LocalRuleValueSelectList(ratings) }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HomePageProductsOnly(x)) { Name = "HomepageProduct", DisplayName = T("Admin.Catalog.Products.Fields.ShowOnHomePage"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.DownloadOnly(x)) { Name = "Download", DisplayName = T("Admin.Catalog.Products.Fields.IsDownload"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.RecurringOnly(x)) { Name = "Recurring", DisplayName = T("Admin.Catalog.Products.Fields.IsRecurring"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.ShipEnabledOnly(x)) { Name = "ShipEnabled", DisplayName = T("Admin.Catalog.Products.Fields.IsShipEnabled"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.FreeShippingOnly(x)) { Name = "FreeShipping", DisplayName = T("Admin.Catalog.Products.Fields.IsFreeShipping"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.TaxExemptOnly(x)) { Name = "TaxExempt", DisplayName = T("Admin.Catalog.Products.Fields.IsTaxExempt"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.EsdOnly(x)) { Name = "Esd", DisplayName = T("Admin.Catalog.Products.Fields.IsEsd"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } }, new SearchFilterDescriptor <bool>((ctx, x) => ctx.Query.HasDiscount(x)) { Name = "Discount", DisplayName = T("Admin.Catalog.Products.Fields.HasDiscountsApplied"), RuleType = RuleType.Boolean, Operators = new RuleOperator[] { RuleOperator.IsEqualTo } } }; if (_services.ApplicationContext.ModuleCatalog.GetModuleByName("SmartStore.MegaSearchPlus") != null) { ISearchFilter[] filters(string fieldName, int parentId, int[] valueIds) { return(valueIds.Select(id => SearchFilter.ByField(fieldName, id).ExactMatch().NotAnalyzed().HasParent(parentId)).ToArray()); } // Sort by display order! var pageIndex = -1; var variantsQuery = _services.DbContext.ProductAttributes .AsNoTracking() .Where(x => x.AllowFiltering) .OrderBy(x => x.DisplayOrder); while (true) { var variants = await variantsQuery.ToPagedList(++pageIndex, 1000).LoadAsync(); foreach (var variant in variants) { var descriptor = new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithFilter(SearchFilter.Combined(filters("variantvalueid", variant.Id, x)))) { Name = $"Variant{variant.Id}", DisplayName = variant.GetLocalized(x => x.Name, language, true, false), GroupKey = "Admin.Catalog.Attributes.ProductAttributes", RuleType = RuleType.IntArray, SelectList = new RemoteRuleValueSelectList("VariantValue") { Multiple = true }, Operators = new RuleOperator[] { RuleOperator.In } }; descriptor.Metadata["ParentId"] = variant.Id; descriptors.Add(descriptor); } if (!variants.HasNextPage) { break; } } pageIndex = -1; var attributesQuery = _services.DbContext.SpecificationAttributes .AsNoTracking() .Where(x => x.AllowFiltering) .OrderBy(x => x.DisplayOrder); while (true) { var attributes = await attributesQuery.ToPagedList(++pageIndex, 1000).LoadAsync(); foreach (var attribute in attributes) { var descriptor = new SearchFilterDescriptor <int[]>((ctx, x) => ctx.Query.WithFilter(SearchFilter.Combined(filters("attrvalueid", attribute.Id, x)))) { Name = $"Attribute{attribute.Id}", DisplayName = attribute.GetLocalized(x => x.Name, language, true, false), GroupKey = "Admin.Catalog.Attributes.SpecificationAttributes", RuleType = RuleType.IntArray, SelectList = new RemoteRuleValueSelectList("AttributeOption") { Multiple = true }, Operators = new RuleOperator[] { RuleOperator.In } }; descriptor.Metadata["ParentId"] = attribute.Id; descriptors.Add(descriptor); } if (!attributes.HasNextPage) { break; } } } descriptors .Where(x => x.RuleType == RuleType.Money) .Each(x => x.Metadata["postfix"] = _services.CurrencyService.PrimaryCurrency.CurrencyCode); return(descriptors.Cast <RuleDescriptor>()); }
public string GetCommonFacetAliasByGroupKind(FacetGroupKind kind, int languageId) { var mappings = GetCommonFacetAliasByGroupKindMappings(); return mappings.Get(FacetUtility.GetFacetAliasSettingKey(kind, languageId, "Forum")); }
protected virtual IDictionary <string, FacetGroup> GetFacets(ForumSearchQuery 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("Forum", key); if (kind == FacetGroupKind.Forum) { var enoughFacets = false; var groups = _forumService.GetAllForumGroups(storeId); foreach (var group in groups) { foreach (var forum in group.Forums) { facets.Add(new Facet(new FacetValue(forum.Id, IndexTypeCode.Int32) { IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(forum.Id)), Label = forum.GetLocalized(x => x.Name, languageId), DisplayOrder = forum.DisplayOrder })); if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount) { enoughFacets = true; break; } } if (enoughFacets) { break; } } } else if (kind == FacetGroupKind.Customer) { // Get customers with most posts. var customerQuery = FacetUtility.GetCustomersByNumberOfPosts( _forumPostRepository, _storeMappingRepository, QuerySettings.IgnoreMultiStore ? 0 : storeId, descriptor.MinHitCount); // Limit the result. Do not allow to get all customers. var maxChoices = descriptor.MaxChoicesCount > 0 ? descriptor.MaxChoicesCount : 20; var take = maxChoices * 3; var customers = customerQuery.Take(() => take).ToList(); foreach (var customer in customers) { var name = customer.FormatUserName(_customerSettings, T, true); if (name.HasValue()) { facets.Add(new Facet(new FacetValue(customer.Id, IndexTypeCode.Int32) { IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(customer.Id)), Label = name, DisplayOrder = 0 })); if (facets.Count >= maxChoices) { break; } } } } else if (kind == FacetGroupKind.Date) { foreach (var value in descriptor.Values) { facets.Add(new Facet(value)); } } if (facets.Any(x => x.Published)) { //facets.Each(x => $"{key} {x.Value.ToString()}".Dump()); var group = new FacetGroup( "Forum", key, descriptor.Label, descriptor.IsMultiSelect, false, descriptor.DisplayOrder, facets.OrderBy(descriptor)) { IsScrollable = facets.Count > 14 }; result.Add(key, group); } } return(result); }
private void AddFacet( CatalogSearchQuery query, FacetGroupKind kind, bool isMultiSelect, FacetSorting sorting, Action <FacetDescriptor> addValues) { string fieldName; var displayOrder = 0; switch (kind) { case FacetGroupKind.Category: fieldName = _catalogSettings.IncludeFeaturedProductsInNormalLists ? "categoryid" : "notfeaturedcategoryid"; break; case FacetGroupKind.Brand: if (_searchSettings.BrandDisabled) { return; } fieldName = "manufacturerid"; displayOrder = _searchSettings.BrandDisplayOrder; break; case FacetGroupKind.Price: if (_searchSettings.PriceDisabled || !_services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices)) { return; } fieldName = "price"; displayOrder = _searchSettings.PriceDisplayOrder; break; case FacetGroupKind.Rating: if (_searchSettings.RatingDisabled) { return; } fieldName = "rating"; displayOrder = _searchSettings.RatingDisplayOrder; break; case FacetGroupKind.DeliveryTime: if (_searchSettings.DeliveryTimeDisabled) { return; } fieldName = "deliveryid"; displayOrder = _searchSettings.DeliveryTimeDisplayOrder; break; case FacetGroupKind.Availability: if (_searchSettings.AvailabilityDisabled) { return; } fieldName = "available"; displayOrder = _searchSettings.AvailabilityDisplayOrder; break; case FacetGroupKind.NewArrivals: if (_searchSettings.NewArrivalsDisabled) { return; } fieldName = "createdon"; displayOrder = _searchSettings.NewArrivalsDisplayOrder; break; default: throw new SmartException($"Unknown field name for facet group '{kind.ToString()}'"); } var descriptor = new FacetDescriptor(fieldName); descriptor.Label = _services.Localization.GetResource(FacetUtility.GetLabelResourceKey(kind) ?? kind.ToString()); descriptor.IsMultiSelect = isMultiSelect; descriptor.DisplayOrder = displayOrder; descriptor.OrderBy = sorting; descriptor.MinHitCount = _searchSettings.FilterMinHitCount; descriptor.MaxChoicesCount = _searchSettings.FilterMaxChoicesCount; addValues(descriptor); query.WithFacet(descriptor); }