Search code examples
.net-corenestelasticsearch-7

ElasticSearch 7 nest 7 return attribute from result all result


I'm using ElarsticSearch 7.7 & NEST 7.7 and on my web page, I'm getting 9 search result documents per page. Even I'm showing the first 9 results on the page, I need to return some property values from all the results for side filtration on the web page.

Eg: if I'm searching "LapTop", my page will show 9 results on the first page. Also, I need to show all the "Manufactures" from all the search results. Not only manufacturers in the first-page result. Then customers can filter by manufacture not only display on the first page. I have tried GlobalAggregation but it returns categories and manufactures only items in selected page.

  public SearchResult Search(SearchType searchType, string searchQuery, int storeId, int pageNumber = 1, int pageSize = 12, IList<SearchFilter> requestFilter = null, decimal? priceFrom = 0, decimal? priceTo = 100000000, string sortBy = null, int totalCount = 0)
            {
                var queryContainer = new QueryContainer();
    
                var sorts = new List<ISort>();
                sorts.Add(new FieldSort { Field = "_score", Order = SortOrder.Descending });
                switch (sortBy)
                {
                    case "z-a":
                        sorts.Add(new FieldSort { Field = Field<ElasticIndexGroupProduct>(p => p.SortValue), Order = SortOrder.Descending });
                        break;
                    case "a-z":
                        sorts.Add(new FieldSort { Field = Field<ElasticIndexGroupProduct>(p => p.SortValue), Order = SortOrder.Ascending });
                        break;               
                }
    
    
                var aggrigations = new AggregationDictionary
                 {
                    {"average_per_child", new 
 AverageAggregation("average_per_child",Field<ElasticIndexGroupProduct>(d =>  d.Price))},
                   {"max_per_child", new MaxAggregation("max_per_child",Field<ElasticIndexGroupProduct>(d => d.Price))},
                    {"min_per_child", new MinAggregation("min_per_child", Field<ElasticIndexGroupProduct>(d => d.Price))},
                    {
                     "globle_filter_aggrigation", new GlobalAggregation("globle_filter_aggrigation")
                    {
                       Aggregations =new AggregationDictionary
                      {
                        {"category_flow",  new TermsAggregation("category_flow"){Field = Field<ElasticIndexGroupProduct>(p => p.CategoryFlow)} },
                        {"manufacturers", new TermsAggregation("manufacturers"){Field = Field<ElasticIndexGroupProduct>(p => p.Manufacturer)} }
                     }
                   }
                  }                   
                };
               
                var searchRequest = new SearchRequest<ElasticIndexGroupProduct>()
                {
                    Profile = true,
                    From = (pageNumber - 1) * pageSize,
                    Size = pageSize,
                    Version = true,
                    Sort = sorts,
                    //Scroll = Time.MinusOne,
                    Aggregations = aggrigations
                };
    
                 var multiMatch = new QueryStringQuery
                 {
                        Query = searchQuery,
                        Fields = GetSearchFields(searchType),
                        Boost = 1.1,
                        Name = "named_query",
                        DefaultOperator = Operator.Or,
                        Analyzer = "standard",
                        QuoteAnalyzer = "keyword",
                        AllowLeadingWildcard = true,
                        MaximumDeterminizedStates = 2,
                        Escape = true,
                        FuzzyPrefixLength = 2,
                        FuzzyMaxExpansions = 3,
                        FuzzyRewrite = MultiTermQueryRewrite.ConstantScore,
                        Rewrite = MultiTermQueryRewrite.ConstantScore,
                        Fuzziness = Fuzziness.Auto,
                        TieBreaker = 1,
                        AnalyzeWildcard = true,
                        MinimumShouldMatch = 2,
                        QuoteFieldSuffix = "'",
                        Lenient = true,
                        AutoGenerateSynonymsPhraseQuery = false
                };
    
                searchRequest.Query = new BoolQuery
                {
                        Must = new QueryContainer[] { multiMatch },
                        Filter = new QueryContainer[] { queryContainer }
                };
    
           var searchResponse = _client.Search<ElasticIndexGroupProduct>(searchRequest);

          var categoryFlowsGlobe = new List<string>();
          var allAggregations = searchResponse.Aggregations.Global("globle_filter_aggrigation");
          var categories = allAggregations.Terms("category_flow");
          foreach (var aggItem in categories.Buckets)
          {
             if (!categoryFlowsGlobe.Any(x => x == aggItem.Key))
             {
               categoryFlowsGlobe.Add(aggItem.Key);
             }
           }
              
    }

Solution

  • This is the exact use case for Post filter - to run a search request that returns hits and aggregations, then to apply filtering to the hits after aggregations have been calculated.

    For Manufacturers, these can be retrieved with a terms aggregation in the search request - you can adjust the size on the aggregation if you need to return all manufacturers, otherwise you might decide to return only the top x.