/// <summary> /// Initializes a new instance of the <see cref="Facet"/> class. /// </summary> /// <param name="group">The group.</param> /// <param name="key">The key.</param> /// <param name="count">The count.</param> /// <param name="labels">The labels.</param> public Facet(FacetGroup group, string key, int count, FacetLabel[] labels) { Group = group; Key = key; Labels = labels; Count = count; }
/// <summary> /// Using the facets returned with the search results, we can bind some filter dropdowns to the Grade, Type, and Year facets /// We must first make sure those facets exist. /// </summary> protected void BindFilters() { FacetGroup gradeFacet = this.Results.FacetGroups.SingleOrDefault(facet => facet.FieldName == "Grade"); if (gradeFacet != null) { this.ddlGradeFilter.DataSource = gradeFacet.Facets; this.ddlGradeFilter.DataBind(); } this.ddlGradeFilter.Items.Insert(0, new ListItem("All Grades")); FacetGroup typeFacet = this.Results.FacetGroups.SingleOrDefault(facet => facet.FieldName == "TypeGroup"); if (typeFacet != null) { this.ddlTypeFilter.DataSource = typeFacet.Facets; this.ddlTypeFilter.DataBind(); } this.ddlTypeFilter.Items.Insert(0, new ListItem("All Types")); FacetGroup yearFacet = this.Results.FacetGroups.SingleOrDefault(facet => facet.FieldName == "Year"); if (yearFacet != null) { this.ddlYearFilter.DataSource = yearFacet.Facets; this.ddlYearFilter.DataBind(); } this.ddlYearFilter.Items.Insert(0, new ListItem("All Years")); }
/// <summary> /// Initializes a new instance of the <see cref="Facet"/> class. /// </summary> /// <param name="group">The group.</param> /// <param name="key">The key.</param> /// <param name="name">The name.</param> /// <param name="count">The count.</param> public Facet(FacetGroup group, string key, string name, int count) { this.Group = group; this.Key = key; this.Name = name; this.Count = count; }
private FacetGroup CalculateResultCount(IndexReader reader, DocIdSet baseDocIdSet, ISearchFilter filter, ISearchCriteria criteria) { FacetGroup result = null; var values = filter.GetValues(); if (values != null) { BooleanFilter ffilter = null; foreach (var f in criteria.CurrentFilters) { if (!f.Key.Equals(filter.Key)) { if (ffilter == null) { ffilter = new BooleanFilter(); } var q = LuceneQueryHelper.CreateQuery(criteria, f, Occur.SHOULD); ffilter.Add(new FilterClause(q, Occur.MUST)); } } var groupLabels = filter.GetLabels(); var facetGroup = new FacetGroup(filter.Key, groupLabels); foreach (var group in values.GroupBy(v => v.Id)) { var value = group.FirstOrDefault(); var valueFilter = LuceneQueryHelper.CreateQueryForValue(Results.SearchCriteria, filter, value); if (valueFilter != null) { var queryFilter = new BooleanFilter(); queryFilter.Add(new FilterClause(valueFilter, Occur.MUST)); if (ffilter != null) { queryFilter.Add(new FilterClause(ffilter, Occur.MUST)); } var filterArray = queryFilter.GetDocIdSet(reader); var newCount = (int)CalculateFacetCount(baseDocIdSet, filterArray); if (newCount > 0) { var valueLabels = group.GetValueLabels(); var newFacet = new Facet(facetGroup, group.Key, newCount, valueLabels); facetGroup.Facets.Add(newFacet); } } } if (facetGroup.Facets.Any()) { result = facetGroup; } } return(result); }
public IViewComponentResult Invoke(FacetGroup facetGroup, string templateName) { Guard.NotNull(facetGroup, nameof(facetGroup)); Guard.NotEmpty(templateName, nameof(templateName)); return(View(templateName, facetGroup)); }
/// <summary> /// Calculates the result count. /// </summary> /// <param name="reader">The reader.</param> /// <param name="baseDocIdSet">The base doc id set.</param> /// <param name="facetGroup">The facet group.</param> /// <param name="filter">The filter.</param> /// <param name="criteria">The criteria.</param> /// <returns></returns> private int CalculateResultCount(IndexReader reader, DocIdSet baseDocIdSet, FacetGroup facetGroup, ISearchFilter filter, ISearchCriteria criteria) { var count = 0; var values = LuceneQueryHelper.GetFilterValues(filter); if (values == null) { return(0); } BooleanFilter ffilter = null; foreach (var f in criteria.CurrentFilters) { if (!f.Key.Equals(facetGroup.FieldName)) { if (ffilter == null) { ffilter = new BooleanFilter(); } var q = LuceneQueryHelper.CreateQuery(criteria, f, Occur.SHOULD); ffilter.Add(new FilterClause(q, Occur.MUST)); } } foreach (var value in values) { var queryFilter = new BooleanFilter(); var valueFilter = LuceneQueryHelper.CreateQueryForValue(Results.SearchCriteria, filter, value); if (valueFilter == null) { continue; } queryFilter.Add(new FilterClause(valueFilter, Occur.MUST)); if (ffilter != null) { queryFilter.Add(new FilterClause(ffilter, Occur.MUST)); } var filterArray = queryFilter.GetDocIdSet(reader); var newCount = (int)CalculateFacetCount(baseDocIdSet, filterArray); if (newCount == 0) { continue; } var newFacet = new Facet(facetGroup, value.Id, GetDescription(value, Results.SearchCriteria.Locale), newCount); facetGroup.Facets.Add(newFacet); count += newCount; } return(count); }
public RouteInfo GetTemplateRoute(FacetGroup facetGroup) { var route = _selectors .OrderByDescending(x => x.Ordinal) .Select(x => x.GetTemplateRoute(facetGroup)) .FirstOrDefault(x => x != null); return(route); }
/// <summary> /// Converts the specified facet group. /// </summary> /// <param name="helper">The helper.</param> /// <param name="group">The facet group.</param> /// <returns> /// facet group /// </returns> public static FilterModel Convert(this ISearchFilterService helper, FacetGroup group) { return(new FilterModel { Key = @group.FieldName, Name = GetDescriptionFromFilter(@group.FieldName), Facets = @group.Facets.Select(x => Convert(helper, x)).ToArray() }); }
private void AddFacetResult(FacetGroup facetGroup, Dictionary <string, FilterFacet> facetsByName, string field, string key, Descriptions descriptions, string locale) { string key1 = FindProviderExtensions.EncodeFacetName(field, key); FilterFacet filterFacet; if (!facetsByName.TryGetValue(key1, out filterFacet) || filterFacet.Count <= 0) { return; } string facetDescription = this.GetFacetDescription(descriptions, locale); Mediachase.Search.Extensions.Facet facet = new Mediachase.Search.Extensions.Facet((ISearchFacetGroup)facetGroup, key, facetDescription, filterFacet.Count); facetGroup.Facets.Add((ISearchFacet)facet); }
public static Aggregation ToModuleModel(this FacetGroup facetGroup, params string[] appliedFilters) { var result = new Aggregation { AggregationType = facetGroup.FacetType, Field = facetGroup.FieldName, Items = facetGroup.Facets.Select(f => f.ToModuleModel(appliedFilters)).ToArray() }; if (facetGroup.Labels != null) { result.Labels = facetGroup.Labels.Select(ToModuleModel).ToArray(); } return(result); }
/// <summary> /// Converts the browser request to facet groups and optionally looks up a display label for the facet value if a facetDisplayDictionaryValues is passed and has a value for the facet alias /// </summary> /// <param name="facetMap"></param> /// <param name="facetDisplayDictionaryValues"></param> /// <returns></returns> public virtual IEnumerable <FacetGroup> ConvertToFacetGroups(Dictionary <string, IFacetAccessible> facetMap, Dictionary <string, Dictionary <string, string> > facetDisplayDictionaryValues = null) { var facetGroups = new List <FacetGroup>(); if (facetMap.Any()) { foreach (var map in facetMap) { var facetField = FacetFields.FirstOrDefault(x => map.Key == x.Alias.FacetFieldAlias()); var group = new FacetGroup { Label = facetField?.Label, Alias = map.Key }; var sortOrder = 0; foreach (var f in map.Value.GetFacets()) { var facetName = f.Value.ToString(); sortOrder++; if (facetDisplayDictionaryValues != null) { if (facetDisplayDictionaryValues.ContainsKey(map.Key) && facetDisplayDictionaryValues[map.Key].ContainsKey(f.Value.ToString())) { facetName = facetDisplayDictionaryValues[map.Key][f.Value.ToString()]; } } else if (facetField != null) { facetName = facetField.CreateValueLabel(f.Value.ToString()); } var facet = new Facet { Label = facetName, Value = f.Value.ToString(), Count = f.HitCount, Sort = sortOrder }; group.Facets.Add(facet); } facetGroups.Add(group); } } return(facetGroups); }
public RouteInfo GetTemplateRoute(FacetGroup facetGroup) { var templateName = GetTemplateName(facetGroup); if (templateName.IsEmpty()) { return(null); } string controller = "Search"; string action = "FacetGroup"; var routeValues = new RouteValueDictionary(new { area = "", facetGroup = facetGroup, templateName = templateName }); return(new RouteInfo(action, controller, routeValues)); }
public virtual Facet FakeFacet( string facetCode, FacetType t, FacetGroup g, bool is_applicable = true ) => new Facet { FacetCode = facetCode, CategoryIdExpr = Guid.NewGuid().ToString(), CategoryNameExpr = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), DisplayTitle = Guid.NewGuid().ToString(), AggregateType = "", AggregateTitle = "", AggregateFacetId = 0, SortExpr = "", FacetGroup = g, FacetType = t, IsApplicable = is_applicable };
private IEnumerable <FacetGroup> BuildFacetResults(SearchResults <FindDocument> results, ISearchCriteria criteria) { List <FacetGroup> facetGroupList = new List <FacetGroup>(); if (results.Facets != null && results.Facets.Any <EPiServer.Find.Api.Facets.Facet>()) { Dictionary <string, FilterFacet> dictionary = results.Facets.OfType <FilterFacet>().ToDictionary <FilterFacet, string, FilterFacet>((Func <FilterFacet, string>)(f => f.Name), (Func <FilterFacet, FilterFacet>)(f => f), (IEqualityComparer <string>)StringComparer.OrdinalIgnoreCase); foreach (SearchFilter filter in criteria.Filters) { string facetDescription = this.GetFacetDescription(filter.Descriptions, criteria.Locale); FacetGroup facetGroup = new FacetGroup(filter.field, facetDescription); if (filter.Values.SimpleValue != null) { foreach (SimpleValue simpleValue in filter.Values.SimpleValue) { this.AddFacetResult(facetGroup, dictionary, filter.field, simpleValue.key, simpleValue.Descriptions, criteria.Locale); } } if (filter.Values.RangeValue != null) { foreach (RangeValue rangeValue in filter.Values.RangeValue) { this.AddFacetResult(facetGroup, dictionary, filter.field, rangeValue.key, rangeValue.Descriptions, criteria.Locale); } } if (filter.Values.PriceRangeValue != null) { foreach (PriceRangeValue priceRangeValue in ((IEnumerable <PriceRangeValue>)filter.Values.PriceRangeValue).Where <PriceRangeValue>((Func <PriceRangeValue, bool>)(prv => string.Equals(prv.currency, (string)criteria.Currency, StringComparison.OrdinalIgnoreCase)))) { this.AddFacetResult(facetGroup, dictionary, filter.field, priceRangeValue.key, priceRangeValue.Descriptions, criteria.Locale); } } if (facetGroup.Facets.Count > 0) { facetGroupList.Add(facetGroup); } } } return((IEnumerable <FacetGroup>)facetGroupList); }
private string GetTemplateName(FacetGroup group) { var prefix = "FacetTemplates/"; switch (group.Kind) { case FacetGroupKind.Category: case FacetGroupKind.DeliveryTime: case FacetGroupKind.Brand: case FacetGroupKind.Availability: case FacetGroupKind.NewArrivals: return(prefix + (group.IsMultiSelect ? "MultiSelect" : "SingleSelect")); case FacetGroupKind.Price: return(prefix + "Price"); case FacetGroupKind.Rating: return(prefix + "Rating"); } return(null); }
public RouteInfo GetTemplateRoute(FacetGroup facetGroup) { // Provide template for catalog only. if (facetGroup.Scope != "Catalog") { return(null); } // Provide template for specifications attributes only. if (facetGroup.Kind != FacetGroupKind.Attribute) { return(null); } // Provide template for admin only (because this is a developer demo). if (!_workContext.CurrentCustomer.IsAdmin()) { return(null); } // TODO: filter by what your template is made for. // E.g. merchant configures a specification attribute in your plugin, then you can filter by facetGroup.Key == "attrid<ConfiguredId>" if (facetGroup.Label.IsCaseInsensitiveEqual("Dimensions") || facetGroup.Label.IsCaseInsensitiveEqual("Maße")) { var routeValues = new RouteValueDictionary(new { area = "SmartStore.DevTools", templateName = "MyCustomFacetTemplate", facetGroup }); return(new RouteInfo("MyCustomFacetTemplate", "DevTools", routeValues)); } return(null); }
public void Init() { instance = new FacetGroup(); }
/// <summary> /// Creates facets. /// </summary> /// <param name="reader">The reader.</param> /// <param name="query">The query.</param> private void CreateFacets(IndexReader reader, Query query) { var groups = new List<FacetGroup>(); var baseQueryFilter = new CachingWrapperFilter(new QueryWrapperFilter(query)); var baseDocIdSet = baseQueryFilter.GetDocIdSet(reader); #region Subcategory filters /* var catalogCriteria = Results.SearchCriteria as CatalogItemSearchCriteria; if (catalogCriteria != null && catalogCriteria.ChildCategoryFilters.Any()) { var group = new FacetGroup("Subcategory"); var groupCount = 0; foreach (var value in catalogCriteria.ChildCategoryFilters) { var q = LuceneQueryHelper.CreateQuery(catalogCriteria.OutlineField, value); if (q == null) continue; var queryFilter = new CachingWrapperFilter(new QueryWrapperFilter(q)); var filterArray = queryFilter.GetDocIdSet(reader); var newCount = (int)CalculateFacetCount(baseDocIdSet, filterArray); if (newCount == 0) continue; var newFacet = new Facet(group, value.Code, value.Name, newCount); group.Facets.Add(newFacet); groupCount += newCount; } // Add only if items exist under if (groupCount > 0) { groups.Add(group); } } * */ #endregion if (Results.SearchCriteria.Filters != null && Results.SearchCriteria.Filters.Length > 0) { foreach (var filter in Results.SearchCriteria.Filters) { var group = new FacetGroup(filter.Key); var groupCount = 0; if (!String.IsNullOrEmpty(Results.SearchCriteria.Currency) && filter is s.PriceRangeFilter) { var valCurrency = ((s.PriceRangeFilter) filter).Currency; if ( !valCurrency.Equals( Results.SearchCriteria.Currency, StringComparison.OrdinalIgnoreCase)) { continue; } } groupCount += CalculateResultCount(reader, baseDocIdSet, group, filter, Results.SearchCriteria); // Add only if items exist under if (groupCount > 0) { groups.Add(group); } } } Results.FacetGroups = groups.ToArray(); }
/// <summary> /// Calculates the result count. /// </summary> /// <param name="reader">The reader.</param> /// <param name="baseDocIdSet">The base doc id set.</param> /// <param name="facetGroup">The facet group.</param> /// <param name="filter">The filter.</param> /// <param name="criteria">The criteria.</param> /// <returns></returns> private int CalculateResultCount(IndexReader reader, DocIdSet baseDocIdSet, FacetGroup facetGroup, ISearchFilter filter, ISearchCriteria criteria) { var count = 0; var values = LuceneQueryHelper.GetFilterValues(filter); if (values == null) { return 0; } BooleanFilter ffilter = null; foreach (var f in criteria.CurrentFilters) { if (!f.Key.Equals(facetGroup.FieldName)) { if (ffilter == null) ffilter = new BooleanFilter(); var q = LuceneQueryHelper.CreateQuery(criteria, f, Occur.SHOULD); ffilter.Add(new FilterClause(q, Occur.MUST)); } } foreach (var value in values) { var queryFilter = new BooleanFilter(); var valueFilter = LuceneQueryHelper.CreateQueryForValue(Results.SearchCriteria, filter, value); if (valueFilter == null) continue; queryFilter.Add(new FilterClause(valueFilter, Occur.MUST)); if(ffilter!=null) queryFilter.Add(new FilterClause(ffilter, Occur.MUST)); var filterArray = queryFilter.GetDocIdSet(reader); var newCount = (int)CalculateFacetCount(baseDocIdSet, filterArray); if (newCount == 0) continue; var newFacet = new Facet(facetGroup, value.Id, GetDescription(value, Results.SearchCriteria.Locale), newCount); facetGroup.Facets.Add(newFacet); count += newCount; } return count; }
public virtual ISearchResults Search(string scope, ISearchCriteria criteria) { var command = new SearchCommand(scope, criteria.DocumentType); command.Size(criteria.RecordsToRetrieve); command.From(criteria.StartingRecord); // Add spell checking // TODO: options.SpellCheck = new SpellCheckingParameters { Collate = true }; // Build query var builder = (QueryBuilder <ESDocument>)_queryBuilder.BuildQuery(criteria); SearchResult <ESDocument> resultDocs; // Add some error handling try { resultDocs = Client.Search(command, builder); } catch (Exception ex) { throw new ElasticSearchException("Search using Elastic Search server failed, check logs for more details.", ex); } // Parse documents returned var documents = new ResultDocumentSet { TotalCount = resultDocs.hits.total }; var docList = new List <ResultDocument>(); foreach (var indexDoc in resultDocs.Documents) { var document = new ResultDocument(); foreach (var field in indexDoc.Keys) { document.Add(new DocumentField(field, indexDoc[field])); } docList.Add(document); } documents.Documents = docList.ToArray(); // Create search results object var results = new SearchResults(criteria, new[] { documents }); // Now add facet results var groups = new List <FacetGroup>(); if (resultDocs.facets != null) { foreach (var filter in criteria.Filters) { var groupCount = 0; var group = new FacetGroup(filter.Key); if (filter is AttributeFilter) { var attributeFilter = filter as AttributeFilter; var myFilter = attributeFilter; var values = myFilter.Values; if (values != null) { var key = filter.Key.ToLower(); if (!resultDocs.facets.ContainsKey(key)) { continue; } var facet = resultDocs.facets[key] as TermsFacetResult; if (facet != null) { foreach (var value in values) { //facet.terms var termCount = from f in facet.terms where f.term.Equals(value.Id, StringComparison.OrdinalIgnoreCase) select f.count; var enumerable = termCount as int[] ?? termCount.ToArray(); if (!enumerable.Any()) { continue; } //var facet = from resultFacet var newFacet = new Facet(@group, value.Id, GetDescription(value, criteria.Locale), enumerable.SingleOrDefault()); @group.Facets.Add(newFacet); } groupCount++; } } } else if (filter is PriceRangeFilter) { var rangeFilter = filter as PriceRangeFilter; if (rangeFilter != null && rangeFilter.Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase)) { var myFilter = rangeFilter; var values = myFilter.Values; if (values != null) { values = rangeFilter.Values; foreach (var value in values) { var key = String.Format("{0}-{1}", myFilter.Key, value.Id).ToLower(); if (!resultDocs.facets.ContainsKey(key)) { continue; } var facet = resultDocs.facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { if (facet.count == 0) { continue; } var myFacet = new Facet( @group, value.Id, GetDescription(value, criteria.Locale), facet.count); @group.Facets.Add(myFacet); groupCount++; } } } } } else if (filter is RangeFilter) { var myFilter = filter as RangeFilter; if (myFilter != null) { var values = myFilter.Values; if (values != null) { foreach (var value in values) { var facet = resultDocs.facets[filter.Key] as FilterFacetResult; if (facet == null || facet.count <= 0) { continue; } var myFacet = new Facet( @group, value.Id, GetDescription(value, criteria.Locale), facet.count); @group.Facets.Add(myFacet); groupCount++; } } } } else if (filter is CategoryFilter) { var myFilter = filter as CategoryFilter; if (myFilter != null) { var values = myFilter.Values; if (values != null) { foreach (var value in values) { var key = String.Format("{0}-{1}", myFilter.Key.ToLower(), value.Id.ToLower()).ToLower(); var facet = resultDocs.facets[key] as FilterFacetResult; if (facet == null || facet.count <= 0) { continue; } var myFacet = new Facet( @group, value.Id, GetDescription(value, criteria.Locale), facet.count); @group.Facets.Add(myFacet); groupCount++; } } } } // Add only if items exist under if (groupCount > 0) { groups.Add(group); } } } results.FacetGroups = groups.ToArray(); return(results); }
public ActionResult MyCustomFacetTemplate(FacetGroup facetGroup, string templateName) { /// Just a "proxy" for our <see cref="Services.CustomFacetTemplateSelector" />. return(PartialView(templateName, facetGroup)); }
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); }
private static FacetGroup[] CreateFacets(ISearchCriteria criteria, SearchResult <ESDocument> .SearchFacets facets) { var result = new List <FacetGroup>(); if (facets != null) { foreach (var filter in criteria.Filters) { var groupLabels = filter.GetLabels(); var facetGroup = new FacetGroup(filter.Key, groupLabels); var values = filter.GetValues(); // Return all facet terms for attribute filter if values are not defined if (values == null && filter is AttributeFilter) { facetGroup.FacetType = FacetTypes.Attribute; var key = filter.Key.ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as TermsFacetResult; if (facet != null) { foreach (var term in facet.terms) { var newFacet = new Facet(facetGroup, term.term, term.count, null); facetGroup.Facets.Add(newFacet); } } } } if (values != null) { foreach (var group in values.GroupBy(v => v.Id)) { var valueLabels = group.GetValueLabels(); if (filter is AttributeFilter) { facetGroup.FacetType = FacetTypes.Attribute; var key = filter.Key.ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as TermsFacetResult; if (facet != null) { var term = facet.terms.FirstOrDefault(t => t.term.Equals(group.Key, StringComparison.OrdinalIgnoreCase)); if (term != null) { var newFacet = new Facet(facetGroup, group.Key, term.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } } else if (filter is PriceRangeFilter) { facetGroup.FacetType = FacetTypes.PriceRange; var rangeFilter = filter as PriceRangeFilter; if (rangeFilter.Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase)) { var key = string.Format(CultureInfo.InvariantCulture, "{0}-{1}", filter.Key, group.Key).ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { var newFacet = new Facet(facetGroup, group.Key, facet.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } } else if (filter is RangeFilter) { facetGroup.FacetType = FacetTypes.Range; var key = filter.Key.ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { var newFacet = new Facet(facetGroup, group.Key, facet.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } else if (filter is CategoryFilter) { facetGroup.FacetType = FacetTypes.Category; var key = string.Format(CultureInfo.InvariantCulture, "{0}-{1}", filter.Key, group.Key).ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { var newFacet = new Facet(facetGroup, group.Key, facet.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } } } // Add facet group only if has items if (facetGroup.Facets.Any()) { result.Add(facetGroup); } } } return(result.ToArray()); }
public async Task <SearchResult <T> > SearchAsync(SearchQuery queryDefinition, CancellationToken cancellationToken = default) { using (await writerLock.ReaderLockAsync(cancellationToken)) { var result = new SearchResult <T>(); List <T> hits = new List <T>(); using (var writer = getWriter()) { Query query = new MatchAllDocsQuery(); // Term queries if (queryDefinition.TermQueries.Any()) { var phraseQuery = new MultiPhraseQuery(); foreach (var termQuery in queryDefinition.TermQueries) { phraseQuery.Add( termQuery.value .Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) .Select(phrase => new Term(termQuery.field, phrase.ToLower())) .ToArray() ); } query = phraseQuery; } var reader = writer.DocsWriter.GetReader(applyAllDeletes: true); var searcher = new IndexSearcher(reader); var luceneResult = searcher.Search(query, queryDefinition.Limit); foreach (var doc in luceneResult.ScoreDocs) { var foundDoc = searcher.Doc(doc.Doc); hits.Add(await inflateDocument(foundDoc)); } result.TotalHits = luceneResult.TotalHits; result.Hits = hits; // Facets if (queryDefinition.Facets.Any()) { FacetsConfig facetsConfig = new FacetsConfig(); FacetsCollector fc = new FacetsCollector(); FacetsCollector.Search(searcher, query, queryDefinition.FacetMax, fc); using (var taxonomyReader = new DirectoryTaxonomyReader(FSDirectory.Open(Path.Combine(options.IndexPath, indexType, "taxonomy")))) { var facets = new FastTaxonomyFacetCounts(taxonomyReader, facetsConfig, fc); foreach (var facet in queryDefinition.Facets) { var facetGroup = new FacetGroup { Field = facet }; facetGroup.Facets = facets.GetTopChildren(queryDefinition.FacetMax, facet).LabelValues .Select(x => new Facet { Key = x.Label, Count = (long)x.Value }) .ToArray(); result.FacetGroups.Add(facetGroup); } } } } return(result); } }
/// <summary> /// Creates facets. /// </summary> /// <param name="reader">The reader.</param> /// <param name="query">The query.</param> private void CreateFacets(IndexReader reader, Query query) { var groups = new List <FacetGroup>(); var baseQueryFilter = new CachingWrapperFilter(new QueryWrapperFilter(query)); var baseDocIdSet = baseQueryFilter.GetDocIdSet(reader); #region Subcategory filters /* * var catalogCriteria = Results.SearchCriteria as CatalogItemSearchCriteria; * if (catalogCriteria != null && catalogCriteria.ChildCategoryFilters.Any()) * { * var group = new FacetGroup("Subcategory"); * var groupCount = 0; * * foreach (var value in catalogCriteria.ChildCategoryFilters) * { * var q = LuceneQueryHelper.CreateQuery(catalogCriteria.OutlineField, value); * * if (q == null) continue; * * var queryFilter = new CachingWrapperFilter(new QueryWrapperFilter(q)); * var filterArray = queryFilter.GetDocIdSet(reader); * var newCount = (int)CalculateFacetCount(baseDocIdSet, filterArray); * if (newCount == 0) continue; * * var newFacet = new Facet(group, value.Code, value.Name, newCount); * group.Facets.Add(newFacet); * groupCount += newCount; * } * * // Add only if items exist under * if (groupCount > 0) * { * groups.Add(group); * } * } * */ #endregion if (Results.SearchCriteria.Filters != null && Results.SearchCriteria.Filters.Length > 0) { foreach (var filter in Results.SearchCriteria.Filters) { var group = new FacetGroup(filter.Key); var groupCount = 0; if (!String.IsNullOrEmpty(Results.SearchCriteria.Currency) && filter is PriceRangeFilter) { var valCurrency = ((PriceRangeFilter)filter).Currency; if ( !valCurrency.Equals( Results.SearchCriteria.Currency, StringComparison.OrdinalIgnoreCase)) { continue; } } groupCount += CalculateResultCount(reader, baseDocIdSet, group, filter, Results.SearchCriteria); // Add only if items exist under if (groupCount > 0) { groups.Add(group); } } } Results.FacetGroups = groups.ToArray(); }
private FacetGroup CalculateResultCount(IndexReader reader, DocIdSet baseDocIdSet, ISearchFilter filter, ISearchCriteria criteria) { FacetGroup result = null; var values = filter.GetValues(); if (values != null) { BooleanFilter ffilter = null; foreach (var f in criteria.CurrentFilters) { if (!f.Key.Equals(filter.Key)) { if (ffilter == null) ffilter = new BooleanFilter(); var q = LuceneQueryHelper.CreateQuery(criteria, f, Occur.SHOULD); ffilter.Add(new FilterClause(q, Occur.MUST)); } } var groupLabels = filter.GetLabels(); var facetGroup = new FacetGroup(filter.Key, groupLabels); foreach (var group in values.GroupBy(v => v.Id)) { var value = group.FirstOrDefault(); var valueFilter = LuceneQueryHelper.CreateQueryForValue(Results.SearchCriteria, filter, value); if (valueFilter != null) { var queryFilter = new BooleanFilter(); queryFilter.Add(new FilterClause(valueFilter, Occur.MUST)); if (ffilter != null) queryFilter.Add(new FilterClause(ffilter, Occur.MUST)); var filterArray = queryFilter.GetDocIdSet(reader); var newCount = (int)CalculateFacetCount(baseDocIdSet, filterArray); if (newCount > 0) { var valueLabels = group.GetValueLabels(); var newFacet = new Facet(facetGroup, group.Key, newCount, valueLabels); facetGroup.Facets.Add(newFacet); } } } if (facetGroup.Facets.Any()) { result = facetGroup; } } return result; }
/// <summary> /// Converts the specified facet group. /// </summary> /// <param name="helper">The helper.</param> /// <param name="group">The facet group.</param> /// <returns> /// facet group /// </returns> public static FilterModel Convert(this SearchHelper helper, FacetGroup group) { return new FilterModel { Key = @group.FieldName, Name = GetDescriptionFromFilter(helper, @group.FieldName), Facets = @group.Facets.Select(x => Convert(helper, x)).ToArray() }; }
/// <summary> /// Converts the specified facet groups into filter model. /// </summary> /// <param name="helper">The helper.</param> /// <param name="groups">The groups.</param> /// <returns> /// FilterModel[][]. /// </returns> public static FilterModel[] Convert(this SearchHelper helper, FacetGroup[] groups) { var list = new List<FilterModel>(); if (groups != null) { list.AddRange(groups.Select(x => Convert(helper, x))); } return list.ToArray(); }
public virtual ISearchResults Search(string scope, ISearchCriteria criteria) { var command = new SearchCommand(scope, criteria.DocumentType); command.Size(criteria.RecordsToRetrieve); command.From(criteria.StartingRecord); // Add spell checking // TODO: options.SpellCheck = new SpellCheckingParameters { Collate = true }; // Build query var builder = (QueryBuilder<ESDocument>)_queryBuilder.BuildQuery(criteria); SearchResult<ESDocument> resultDocs; // Add some error handling try { resultDocs = Client.Search(command, builder); } catch (Exception ex) { throw new ElasticSearchException("Search using Elastic Search server failed, check logs for more details.", ex); } // Parse documents returned var documents = new ResultDocumentSet { TotalCount = resultDocs.hits.total }; var docList = new List<ResultDocument>(); foreach (var indexDoc in resultDocs.Documents) { var document = new ResultDocument(); foreach (var field in indexDoc.Keys) document.Add(new DocumentField(field, indexDoc[field])); docList.Add(document); } documents.Documents = docList.ToArray(); // Create search results object var results = new SearchResults(criteria, new[] { documents }); // Now add facet results var groups = new List<FacetGroup>(); if (resultDocs.facets != null) { foreach (var filter in criteria.Filters) { var groupCount = 0; var group = new FacetGroup(filter.Key); if (filter is AttributeFilter) { group.FacetType = FacetTypes.Attribute; var attributeFilter = filter as AttributeFilter; var myFilter = attributeFilter; var values = myFilter.Values; if (values != null) { var key = filter.Key.ToLower(); if (!resultDocs.facets.ContainsKey(key)) continue; var facet = resultDocs.facets[key] as TermsFacetResult; if (facet != null) { foreach (var value in values) { //facet.terms var termCount = from f in facet.terms where f.term.Equals(value.Id, StringComparison.OrdinalIgnoreCase) select f.count; var enumerable = termCount as int[] ?? termCount.ToArray(); if (!enumerable.Any()) continue; //var facet = from resultFacet var newFacet = new Facet(@group, value.Id, GetDescription(value, criteria.Locale), enumerable.SingleOrDefault()); @group.Facets.Add(newFacet); } groupCount++; } } } else if (filter is PriceRangeFilter) { group.FacetType = FacetTypes.PriceRange; var rangeFilter = filter as PriceRangeFilter; if (rangeFilter != null && rangeFilter.Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase)) { var myFilter = rangeFilter; var values = myFilter.Values; if (values != null) { values = rangeFilter.Values; foreach (var value in values) { var key = String.Format("{0}-{1}", myFilter.Key, value.Id).ToLower(); if (!resultDocs.facets.ContainsKey(key)) continue; var facet = resultDocs.facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { if (facet.count == 0) continue; var myFacet = new Facet( @group, value.Id, GetDescription(value, criteria.Locale), facet.count); @group.Facets.Add(myFacet); groupCount++; } } } } } else if (filter is RangeFilter) { group.FacetType = FacetTypes.Range; var myFilter = filter as RangeFilter; if (myFilter != null) { var values = myFilter.Values; if (values != null) { foreach (var value in values) { var facet = resultDocs.facets[filter.Key] as FilterFacetResult; if (facet == null || facet.count <= 0) { continue; } var myFacet = new Facet( @group, value.Id, GetDescription(value, criteria.Locale), facet.count); @group.Facets.Add(myFacet); groupCount++; } } } } else if (filter is CategoryFilter) { group.FacetType = FacetTypes.Category; var myFilter = filter as CategoryFilter; if (myFilter != null) { var values = myFilter.Values; if (values != null) { foreach (var value in values) { var key = String.Format("{0}-{1}", myFilter.Key.ToLower(), value.Id.ToLower()).ToLower(); var facet = resultDocs.facets[key] as FilterFacetResult; if (facet == null || facet.count <= 0) { continue; } var myFacet = new Facet( @group, value.Id, GetDescription(value, criteria.Locale), facet.count); @group.Facets.Add(myFacet); groupCount++; } } } } // Add only if items exist under if (groupCount > 0) { groups.Add(group); } } } results.FacetGroups = groups.ToArray(); return results; }
private static FacetGroup[] CreateFacets(ISearchCriteria criteria, SearchResult<ESDocument>.SearchFacets facets) { var result = new List<FacetGroup>(); if (facets != null) { foreach (var filter in criteria.Filters) { var groupLabels = filter.GetLabels(); var facetGroup = new FacetGroup(filter.Key, groupLabels); var values = filter.GetValues(); // Return all facet terms for attribute filter if values are not defined if (values == null && filter is AttributeFilter) { facetGroup.FacetType = FacetTypes.Attribute; var key = filter.Key.ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as TermsFacetResult; if (facet != null) { foreach (var term in facet.terms) { var newFacet = new Facet(facetGroup, term.term, term.count, null); facetGroup.Facets.Add(newFacet); } } } } if (values != null) { foreach (var group in values.GroupBy(v => v.Id)) { var valueLabels = group.GetValueLabels(); if (filter is AttributeFilter) { facetGroup.FacetType = FacetTypes.Attribute; var key = filter.Key.ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as TermsFacetResult; if (facet != null) { var term = facet.terms.FirstOrDefault(t => t.term.Equals(group.Key, StringComparison.OrdinalIgnoreCase)); if (term != null) { var newFacet = new Facet(facetGroup, group.Key, term.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } } else if (filter is PriceRangeFilter) { facetGroup.FacetType = FacetTypes.PriceRange; var rangeFilter = filter as PriceRangeFilter; if (rangeFilter.Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase)) { var key = string.Format(CultureInfo.InvariantCulture, "{0}-{1}", filter.Key, group.Key).ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { var newFacet = new Facet(facetGroup, group.Key, facet.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } } else if (filter is RangeFilter) { facetGroup.FacetType = FacetTypes.Range; var key = filter.Key.ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { var newFacet = new Facet(facetGroup, group.Key, facet.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } else if (filter is CategoryFilter) { facetGroup.FacetType = FacetTypes.Category; var key = string.Format(CultureInfo.InvariantCulture, "{0}-{1}", filter.Key, group.Key).ToLower(); if (facets.ContainsKey(key)) { var facet = facets[key] as FilterFacetResult; if (facet != null && facet.count > 0) { var newFacet = new Facet(facetGroup, group.Key, facet.count, valueLabels); facetGroup.Facets.Add(newFacet); } } } } } // Add facet group only if has items if (facetGroup.Facets.Any()) { result.Add(facetGroup); } } } return result.ToArray(); }
public ActionResult ProviderModelQuery(string keyWord) { // Create criteria CatalogEntrySearchCriteria criteria = new CatalogEntrySearchCriteria { RecordsToRetrieve = 200, // there is a default of 50 // Locale have to be there... else no hits Locale = ContentLanguage.PreferredCulture.TwoLetterISOLanguageName, SearchPhrase = keyWord }; // Add more to the criteria criteria.Sort = CatalogEntrySearchCriteria.DefaultSortOrder; criteria.CatalogNames.Add("Fashion"); // ...if we know what catalog to search in, not mandatory //criteria.IgnoreFilterOnLanguage = true; // if we want to search all languages... need the locale anyway criteria.ClassTypes.Add(EntryType.Variation); criteria.MarketId = MarketId.Default; // should use the ICurrentMarket service, of course... criteria.IsFuzzySearch = true; criteria.FuzzyMinSimilarity = 0.7F; criteria.IncludeInactive = true; // the _outline field System.Collections.Specialized.StringCollection sc = new System.Collections.Specialized.StringCollection { "Fashion/Clothes_1/Men_1/Shirts_1", "Fashion/Clothes_1/UniSex_1" }; criteria.Outlines = sc; // another "AND" #region SimpleWalues ///* // Add facets to the criteria... and later prepare them for the "search result" as FacetGroups // With the below only these values are in the result... no Red or RollsRoys Mediachase.Search.SimpleValue svWhite = new SimpleValue { value = "white", key = "white", locale = "en", Descriptions = new Descriptions { defaultLocale = "en" } }; var descWhite = new Description { locale = "en", Value = "White" }; svWhite.Descriptions.Description = new[] { descWhite }; // If added like this it ends up in "ActiveFields" of the criteria and the result is filtered //criteria.Add("color", svWhite); // ...also the facetGroups on the "result" are influenced Mediachase.Search.SimpleValue svBlue = new SimpleValue { value = "blue", key = "blue", locale = "en", Descriptions = new Descriptions { defaultLocale = "en" } }; var descBlue = new Description { locale = "en", Value = "Blue" }; svBlue.Descriptions.Description = new[] { descBlue }; //criteria.Add("color", svBlue); Mediachase.Search.SimpleValue svVolvo = new SimpleValue { value = "volvo", key = "volvo", locale = "en", Descriptions = new Descriptions { defaultLocale = "en" } }; var descVolvo = new Description { locale = "en", Value = "volvo" }; svVolvo.Descriptions.Description = new[] { descVolvo }; //criteria.Add("brand", svVolvo); Mediachase.Search.SimpleValue svSaab = new SimpleValue { value = "saab", key = "saab", locale = "en", Descriptions = new Descriptions { defaultLocale = "en" } }; var descSaab = new Description { locale = "en", Value = "saab" }; svSaab.Descriptions.Description = new[] { descSaab }; //criteria.Add("brand", svSaab); #region Debug // the above filters the result so only saab (the blue) is there // With the above only we see only the Blue shirt... is that a saab - yes // New: no xml --> gives one Active and an empty filter even searchFilter.Values.SimpleValue below is there // New: outcommenting the above line --> and add XML file ... no "Active Fileds" // Have the Filters added - but no actice fields // New: trying this... Brand gets "ActiveField" with volvo & saab.. but the result shows all brands // New: outcommenting the below line and adding above only one, the saab //criteria.Add("brand", new List<ISearchFilterValue> { svSaab, svVolvo }); // ...get a FacetGroups "in there"... like with the XML-file ... a manual way to add... // ...stuff that is not in the XML-file, or skip the XML File // New: taking out the single saab filter added #endregion SearchFilter searchFilterColor = new SearchFilter { //field = BaseCatalogIndexBuilder.FieldConstants.Catalog, // Have a bunch field = "color", // mandatory Descriptions = new Descriptions { // another way of getting the language defaultLocale = _langResolver.Service.GetPreferredCulture().Name }, Values = new SearchFilterValues(), }; SearchFilter searchFilterBrand = new SearchFilter { field = "brand", Descriptions = new Descriptions { defaultLocale = _langResolver.Service.GetPreferredCulture().Name }, Values = new SearchFilterValues(), }; var descriptionColor = new Description { locale = "en", Value = "Color" }; var descriptionBrand = new Description { locale = "en", Value = "Brand" }; searchFilterColor.Descriptions.Description = new[] { descriptionColor }; searchFilterBrand.Descriptions.Description = new[] { descriptionBrand }; searchFilterColor.Values.SimpleValue = new SimpleValue[] { svWhite, svBlue }; searchFilterBrand.Values.SimpleValue = new SimpleValue[] { svVolvo, svSaab }; // can do like the below or us the loop further down... // the "foreach (SearchFilter item in _NewSearchConfig.SearchFilters)" // use these in the second part of the demo... "without XML" ... saw that with XML-style criteria.Add(searchFilterColor); criteria.Add(searchFilterBrand); #region Debug // gets the "filters" without this below and the XML... further checks... // do we need this? ... seems not... or it doesn't work like this // New: Have XML and commenting out the below lines Looks the same as with it // New: second...outcommenting the criteria.Add(searchFilter); // the Facets prop is empty......without the XML // the below line seems not to work // New: adding these again together with the saab above active //... difference is the "VariationFilter" // We get the Facets on the criteria, but no facets in the "result" without the XML //criteria.Filters = searchFilter; // read-only // Without the XML... // boom... on a missing "key"... the description // when commenting out the criteria.Add() for the simple values...?? // When adding more to the SearchFilter it works... // ... the Simple values are there in the only instance if the filter // commenting out and check with the XML // when using the XML the groups sit in FacetGroups // when using the above... no facet-groups added // The same facets added a second time, Filter number 2 and no facet-groups //SearchConfig sConf = new SearchConfig(); #endregion Debug //*/ #endregion SimpleValues // use the manager for search and for index management SearchManager manager = new SearchManager("ECApplication"); #region Facets/Filters // Filters from the XML file, populates the FacetGroups on the Search result string _SearchConfigPath = @"C:\Episerver612\CommerceTraining\CommerceTraining\Configs\Mediachase.Search.Filters.config"; TextReader reader = new StreamReader(_SearchConfigPath); XmlSerializer serializer = new XmlSerializer((typeof(SearchConfig))); _SearchConfig = (SearchConfig)serializer.Deserialize(reader); reader.Close(); foreach (SearchFilter filter in _SearchConfig.SearchFilters) { // Step 1 - use the XML file //criteria.Add(filter); } // Manual... SearchConfig _NewSearchConfig = new SearchConfig { SearchFilters = new SearchFilter[] { searchFilterColor, searchFilterBrand } }; // can do like this, but there is another way (a bit above) foreach (SearchFilter item in _NewSearchConfig.SearchFilters) { // Step 2 - skip the XML file //criteria.Add(item); } #endregion // Do search ISearchResults results = manager.Search(criteria); #region Debug // doens't work //FacetGroup facetGroup = new FacetGroup("Bogus", "Bummer"); //results.FacetGroups = new[] { facetGroup }; // ...different return types - same method //SearchFilterHelper.Current.SearchEntries() // out comment and do a new try //ISearchFacetGroup[] facets = results.FacetGroups; // NEW: adding these ... for the provider, last line doesn's assign //ISearchFacetGroup[] searchFacetGroup0 = new SearchFacetGroup() { }; FacetGroup facetGroup0 = new FacetGroup("colorgroup", "dummy"); //{ "",""}; // FacetGroup("brand","volvo"); Facet f1 = new Facet(facetGroup0, svWhite.key, svWhite.value, 1); facetGroup0.Facets.Add(f1); //facets[1] = facetGroup0; ISearchFacetGroup[] searchFacetGroup = new FacetGroup[] { facetGroup0 }; //searchFacetGroup.Facets.Add(f1); //results.FacetGroups = searchFacetGroup; // nothing happens here, facet-group still empty #endregion int[] ints = results.GetKeyFieldValues <int>(); // The DTO-way CatalogEntryDto dto = _catalogSystem.GetCatalogEntriesDto(ints); // CMS style (better)... using ReferenceConverter and ContentLoader List <ContentReference> refs = new List <ContentReference>(); ints.ToList().ForEach(i => refs.Add(_referenceConverter.GetContentLink(i, CatalogContentType.CatalogEntry, 0))); localContent = _contentLoader.GetItems(refs, new LoaderOptions()); // // ToDo: Facets List <string> facetList = new List <string>(); int facetGroups = results.FacetGroups.Count(); foreach (ISearchFacetGroup item in results.FacetGroups) { foreach (var item2 in item.Facets) { facetList.Add(String.Format("{0} {1} ({2})", item.Name, item2.Name, item2.Count)); } } var searchResultViewModel = new SearchResultViewModel { totalHits = new List <string> { "" }, // change nodes = localContent.OfType <FashionNode>(), products = localContent.OfType <ShirtProduct>(), variants = localContent.OfType <ShirtVariation>(), allContent = localContent, facets = facetList }; return(View(searchResultViewModel)); }
/// <summary> /// Creates facets. /// </summary> /// <param name="reader">The reader.</param> /// <param name="query">The query.</param> private void CreateFacets(IndexReader reader, Query query) { var groups = new List<FacetGroup>(); if (this.Results.SearchCriteria.Filters != null && this.Results.SearchCriteria.Filters.Length > 0) { var baseQueryFilter = new CachingWrapperFilter(new QueryWrapperFilter(query)); var baseBitArray = baseQueryFilter.GetDocIdSet(reader); foreach (var filter in this.Results.SearchCriteria.Filters) { var group = new FacetGroup(filter.Key); var groupCount = 0; if (!String.IsNullOrEmpty(this.Results.SearchCriteria.Currency) && filter is s.PriceRangeFilter) { var valCurrency = ((s.PriceRangeFilter)filter).Currency; if ( !valCurrency.Equals( this.Results.SearchCriteria.Currency, StringComparison.OrdinalIgnoreCase)) { continue; } } groupCount += this.CalculateResultCount( reader, baseBitArray, group, filter, this.Results.SearchCriteria.Currency); // Add only if items exist under if (groupCount > 0) { groups.Add(group); } } } this.Results.FacetGroups = groups.ToArray(); }
public ActionResult FacetGroup(FacetGroup facetGroup, string templateName) { // Just a "proxy" for our "DefaultFacetTemplateSelector" return(PartialView(templateName, facetGroup)); }
/// <summary> /// Calculates the result count. /// </summary> /// <param name="reader">The reader.</param> /// <param name="baseDocIdSet">The base doc id set.</param> /// <param name="facetGroup">The facet group.</param> /// <param name="filter">The filter.</param> /// <param name="currency">The currency.</param> /// <returns></returns> private int CalculateResultCount( IndexReader reader, DocIdSet baseDocIdSet, FacetGroup facetGroup, ISearchFilter filter, string currency) { var count = 0; ISearchFilterValue[] values = null; var priceQuery = false; if (filter is s.AttributeFilter) { values = ((s.AttributeFilter)filter).Values; } else if (filter is s.RangeFilter) { values = ((s.RangeFilter)filter).Values; } else if (filter is s.PriceRangeFilter) { values = ((s.PriceRangeFilter)filter).Values; priceQuery = true; } if (values == null) { return 0; } foreach (var value in values) { Query q = null; if (priceQuery) { q = LuceneQueryHelper.CreateQuery( this.Results.SearchCriteria, filter.Key, value as s.RangeFilterValue); } else { q = LuceneQueryHelper.CreateQuery(filter.Key, value); } if (q == null) continue; var queryFilter = new CachingWrapperFilter(new QueryWrapperFilter(q)); var filterArray = queryFilter.GetDocIdSet(reader); var newCount = (int)this.CalculateFacetCount(baseDocIdSet, filterArray); if (newCount == 0) continue; var newFacet = new Facet(facetGroup, value.Id, this.GetDescription(value, this.Results.SearchCriteria.Locale), newCount); facetGroup.Facets.Add(newFacet); count += newCount; } return count; }
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); }
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); }
public IEnumerable <IHit> Query(int pageIndex, int pageSize, out int totalCount, out IEnumerable <FacetGroup> facetedResults) { totalCount = 0; facetedResults = null; if (searchPaths == null || searchPaths.Count <= 0) { searchPaths.AddRange(indexPaths.Values.Select(o => o.Path)); } List <LuceneHit> results = new List <LuceneHit>(); List <IndexSearcher> subSearchs = new List <IndexSearcher>(); searchPaths.ForEach(o => subSearchs.Add(new IndexSearcher(FSDirectory.Open(o)))); if (facetFields != null && facetFields.Count > 0) { var facetGroups = new List <FacetGroup>(); var mainQueryFilter = new CachingWrapperFilter(new QueryWrapperFilter(query)); MultiReader readers = new MultiReader(subSearchs.Select(o => o.IndexReader).ToArray()); foreach (var facetField in facetFields) { FacetGroup fg = new FacetGroup(); fg.FieldName = facetFieldNameProvider.GetMapName(TypeName, facetField); var items = new List <FacetItem>(); var allDistinctField = FieldCache_Fields.DEFAULT.GetStrings(readers, facetField).Distinct().ToArray(); int totalHits = 0; Parallel.ForEach(allDistinctField, fieldValue => { //foreach (var fieldValue in allDistinctField) //{ var facetQuery = new TermQuery(new Term(facetField, fieldValue)); var facetQueryFilter = new CachingWrapperFilter(new QueryWrapperFilter(facetQuery)); var bs = new OpenBitSetDISI(facetQueryFilter.GetDocIdSet(readers).Iterator(), readers.MaxDoc); bs.InPlaceAnd(mainQueryFilter.GetDocIdSet(readers).Iterator()); int count = (Int32)bs.Cardinality(); FacetItem item = new FacetItem(); item.GroupValue = fieldValue; item.Count = count; items.Add(item); totalHits += count; } ); fg.FacetItems = items.OrderByDescending(o => o.Count); fg.TotalHits = totalHits; facetGroups.Add(fg); } facetedResults = facetGroups.OrderBy(o => o.FieldName); } ParallelMultiSearcher searcher = new ParallelMultiSearcher(subSearchs.ToArray()); Sort sort = null; if (sortFields != null && sortFields.Count > 0) { sort = new Sort(sortFields.ToArray()); } int maxDoc = searcher.MaxDoc; int startIndex = 0; if (pageIndex >= 0 && pageSize > 0) { startIndex = pageIndex * pageSize; maxDoc = pageSize * (pageIndex + 1); } var docs = sort == null?searcher.Search(query, null, maxDoc) : searcher.Search(query, null, maxDoc, sort); totalCount = docs.TotalHits; int endIndex = docs.TotalHits - startIndex; for (int i = startIndex; i < endIndex; i++) { LuceneHit h = new LuceneHit(TypeName, DocumentBuilder, searcher.Doc(docs.ScoreDocs[i].Doc)); results.Add(h); } return(results); }