public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			if (reader.TokenType != JsonToken.StartArray) return null;
			var fields = new Fields();
			while (reader.TokenType != JsonToken.EndArray)
			{
				var field = reader.ReadAsString();
				if (reader.TokenType == JsonToken.String)
					fields.And(field);
			}
			return fields;
		}
        public IActionResult Index(SearchQueryModel model)
        {
            //Search data
            //http://localhost:9200/person_full_details/_search
            //Search exact term (case-insensitive)

            /*var searchResponse = _elasticClient.Search<PersonFullDetails>(s => s
             *  .From(0)
             *  .Size(10)
             *  .Query(q => q
             *      .Match(m => m
             *          .Field(f => f.Firstname)
             *          .Query("gil*")
             *      )
             *  )
             * );*/
            //Search start with
            var searchResponse = _elasticClient.Search <PersonFullDetails>(s => s
                                                                           .From(0)
                                                                           .Size(10)
                                                                           .Query(q => q
                                                                                  .Prefix(m => m
                                                                                          .Field(f => f.Firstname)
                                                                                          .Value("gil")
                                                                                          )
                                                                                  )
                                                                           );
            var people = searchResponse.Documents;

            //Low-level search
            var searchResponseLowLevel = _elasticClient.LowLevel.Search <SearchResponse <PersonFullDetails> >(PostData.Serializable(new
            {
                from  = 0,
                size  = 10,
                query = new
                {
                    match = new
                    {
                        field = "firstname",
                        query = "gilles"
                    }
                }
            }));
            var responseJsonLowLevel = searchResponseLowLevel;

            //Aggregates
            //TODO: Order bu last/first
            var searchResponseAggOLD = _elasticClient.Search <PersonFullDetails>(s => s
                                                                                 .From((model.Page - 1) * model.PageSize)
                                                                                 .Size(model.PageSize)
                                                                                 //.Size(0)
                                                                                 .Query(q => q
                                                                                        .MatchAll()

                                                                                        /*.Match(m => m
                                                                                         *  .Field(f => f.Firstname)
                                                                                         *  .Query("gilles")
                                                                                         * )*/
                                                                                        )
                                                                                 .Aggregations(a => a
                                                                                               .Terms("last_names", ta => ta
                                                                                                      .Field(f => f.Lastname.Suffix("keyword"))
                                                                                                      )
                                                                                               .Terms("roles", ta => ta
                                                                                                      .Field(f => f.Roles.Suffix("keyword"))
                                                                                                      )
                                                                                               .Terms("company_names", ta => ta
                                                                                                      .Field(f => f.Company.Name.Suffix("keyword"))
                                                                                                      )
                                                                                               )
                                                                                 );

            var searchQuery = new SearchDescriptor <PersonFullDetails>()
                              .From((model.Page - 1) * model.PageSize)
                              .Size(model.PageSize);
            //Term

            /*searchQuery = searchQuery
             *  .Query(qu => qu
             *      .Bool(b => b
             *          //Term
             *          .Must(must => must
             *              .Match(m => m
             *                  .Field(f => f.Firstname)
             *                  .Query(model.Term)
             *                  )
             *              )
             *          //Filter
             *          .Filter(f =>
             *              f.Match(term => term//Term?
             *                  .Field(field => field.Lastname)
             *                  .Query("Dupont")//Value?
             *              )
             *          )
             *      )
             *  );*/

            //TODO: Clean next lines
            var lastnames = model.LastnameFilterValues ?? new string[] { };
            var companies = model.CompanyFilterValues ?? new string[] { };
            var roles     = model.RoleFilterValues ?? new string[] { };
            var filters   = new List <Func <QueryContainerDescriptor <PersonFullDetails>, QueryContainer> >();

            //TODO: Include 1+ filters
            if (lastnames.Any(i => i != null))
            {
                foreach (var lastname in lastnames)
                {
                    filters.Add(fq => fq.Match(t => t.Field(f => f.Lastname).Query(lastname)));
                }
            }
            if (companies.Any(i => i != null))
            {
                foreach (var company in companies)
                {
                    filters.Add(fq => fq.Match(t => t.Field(f => f.Company.Name).Query(company)));
                }
            }
            if (roles.Any(i => i != null))
            {
                foreach (var role in roles)
                {
                    filters.Add(fq => fq.Match(t => t.Field(f => f.Roles).Query(role)));
                }
            }

            Fields firstnameField = Infer.Field <PersonFullDetails>(p => p.Firstname);
            var    lastnameField  = Infer.Field <PersonFullDetails>(p => p.Lastname, 2);//Boost 2, more important
            var    bioField       = Infer.Field <PersonFullDetails>(p => p.Bio);

            searchQuery = searchQuery
                          .Query(qu => qu
                                 .Bool(b => b
                                       //Term
                                       .Must(must => must
                                       //.Match(m => m
                                             .MultiMatch(m => m
                                       //.Field(f => f.Firstname)
                                                         .Fields(firstnameField.And(lastnameField).And(bioField))
                                                         .Query(model.Term)
                                                         )
                                             )
                                       //Filter
                                       .Filter(filters)

                                       /*.Filter(f =>
                                        *  f.Match(term => term//Term?
                                        *      .Field(field => field.Lastname)
                                        *      .Query(model.NameFilterValue)//Value?
                                        *  )
                                        * )*/
                                       )
                                 ).Highlight(h => h
                                             .PreTags("<b>")
                                             .PostTags("</b>")
                                             .Fields(f => f
                                                     .Field(e => e.Bio)
                                                     .PreTags("<span class=\"highlighted\">")
                                                     .PostTags("</span>")
                                                     )
                                             );

            //Aggregates
            searchQuery = searchQuery
                          .Aggregations(a => a
                                        .Terms("last_names", ta => ta
                                               .Field(f => f.Lastname.Suffix("keyword"))
                                               )
                                        .Terms("roles", ta => ta
                                               .Field(f => f.Roles.Suffix("keyword"))
                                               )
                                        .Terms("company_names", ta => ta
                                               .Field(f => f.Company.Name.Suffix("keyword"))
                                               )
                                        );
            var searchResponseAgg = _elasticClient.Search <PersonFullDetails>(searchQuery);

            /*var search2 = new SearchDescriptor<PersonFullDetails>()
             * .Query(q => q
             *     .QueryString(queryString => queryString
             *         .Query("gilles")))
             * .Aggregations(a => a
             *     .Terms("last_names", term => term
             *         .Field(f => f.Lastname.Suffix("keyword"))));*/

            //var search21 = _elasticClient.Search<PersonFullDetails>(search2);

            var results = new List <SearchPersonModel>();
            var i       = 0;

            foreach (var hit in searchResponseAgg.Hits)
            {
                var document = hit.Source;
                foreach (var highlight in hit.Highlight)
                {
                    if (highlight.Key == "bio")
                    {
                        document.Bio = highlight.Value.FirstOrDefault();
                    }
                }
                results.Add(new SearchPersonModel
                {
                    Id        = document.Id,
                    Firstname = document.Firstname,
                    Lastname  = document.Lastname,
                    Age       = document.Age,
                    Bio       = document.Bio,
                    Roles     = document.Roles,
                    Company   = new SearchCompanyModel
                    {
                        Id   = document.Company.Id,
                        Name = document.Company.Name
                    }
                });
                i++;
            }

            var filterGroups = new List <SearchFilterGroup>();
            //Lastname
            var lastnameFilters = new List <SearchFilter>();

            foreach (var bucket in searchResponseAgg.Aggregations.Terms("last_names").Buckets)
            {
                lastnameFilters.Add(new SearchFilter
                {
                    Label = bucket.Key,
                    Count = bucket.DocCount ?? 0
                });
            }
            var lastnameFilterGroup = new SearchFilterGroup
            {
                Label   = "Lastname",
                Filters = lastnameFilters
            };

            filterGroups.Add(lastnameFilterGroup);
            //Role
            var roleFilters = new List <SearchFilter>();

            foreach (var bucket in searchResponseAgg.Aggregations.Terms("roles").Buckets)
            {
                roleFilters.Add(new SearchFilter
                {
                    Label = bucket.Key,
                    Count = bucket.DocCount ?? 0
                });
            }
            var roleFilterGroup = new SearchFilterGroup
            {
                Label   = "Role",
                Filters = roleFilters
            };

            filterGroups.Add(roleFilterGroup);
            //Company
            var companyFilters = new List <SearchFilter>();

            foreach (var bucket in searchResponseAgg.Aggregations.Terms("company_names").Buckets)
            {
                companyFilters.Add(new SearchFilter
                {
                    Label = bucket.Key,
                    Count = bucket.DocCount ?? 0
                });
            }
            var companyFilterGroup = new SearchFilterGroup
            {
                Label   = "Company",
                Filters = companyFilters
            };

            filterGroups.Add(companyFilterGroup);

            var totalPages = searchResponseAgg.Total / (double)model.PageSize;
            var data       = new SearchResultModel
            {
                SearchTerm           = model.Term,
                NbTotalResults       = searchResponseAgg.Total,
                Results              = results,
                FilterGroups         = filterGroups,
                PageSize             = model.PageSize,
                CurrentPage          = model.Page,
                TotalPages           = (int)Math.Ceiling(totalPages),
                LastnameFilterValues = model.LastnameFilterValues,
                CompanyFilterValues  = model.CompanyFilterValues,
                RoleFilterValues     = model.RoleFilterValues
            };

            return(View(data));
        }
Exemple #3
0
        /// <summary>
        /// Search on index
        /// </summary>
        public QueryResult <T> Execute()
        {
            string         indexName     = (new T()).IndexAlias;
            QueryContainer criteriaQuery = null;
            var            sortingQuery  = new List <ISort>();

            if (searchInfo.Fields.Count > 0)
            {
                criteriaQuery = Helper.BuildQuery(searchInfo);
                //create sorting
                foreach (var sort in searchInfo.Sort)
                {
                    if (sort is EsGeoSort <T> )
                    {
                        var gsort = (EsGeoSort <T>)sort;
                        sortingQuery.Add(new GeoDistanceSort {
                            Field = gsort.Field, Unit = DistanceUnit.Meters, DistanceType = GeoDistanceType.Plane, Points = gsort.Points, Order = gsort.Ascending ? SortOrder.Ascending : SortOrder.Descending
                        });
                    }
                    else
                    {
                        sortingQuery.Add(new FieldSort {
                            Field = sort.Field, Order = sort.Ascending ? SortOrder.Ascending : SortOrder.Descending
                        });
                    }
                }
            }
            else
            {
                criteriaQuery = new MatchAllQuery();
            }
            var searchRequest = new SearchRequest <T>(indexName)
            {
                Query = criteriaQuery,
                From  = Start,
                Size  = MaxResults
            };

            //Set source columns
            if (searchInfo.Source.Count > 0)
            {
                var    sourceFilter = new SourceFilter();
                var    bfields      = searchInfo.Source[0];
                Fields fields       = bfields;
                for (int i = 1; i < searchInfo.Source.Count; i++)
                {
                    fields = fields.And(searchInfo.Source[i]);
                }

                sourceFilter.Includes = fields;

                searchRequest.Source = sourceFilter;
            }

            //Sorting
            if (sortingQuery.Count > 0)
            {
                searchRequest.Sort = sortingQuery;
            }

            //Aggregations
            if (searchInfo.Aggregations.Count() > 0)
            {
                searchRequest.Aggregations = searchInfo.Aggregations;
            }
            if (searchInfo.termDictionary.Count > 0)
            {
                if (searchRequest.Aggregations == null)
                {
                    searchRequest.Aggregations = new AggregationDictionary();
                }

                foreach (var term in searchInfo.termDictionary)
                {
                    searchRequest.Aggregations.Add(term.Key, term.Value);
                }
            }
            //Send request
            var searchResponse = Manager.EsClient.Search <T>(searchRequest);

            if (!searchResponse.IsValid)
            {
                throw new Exception("Low Level Fail Call.", searchResponse.OriginalException);
            }
            //handle result
            _result = new QueryResult <T>
            {
                Documents   = searchResponse.Documents.AsEnumerable(),
                Scores      = searchResponse.Hits.Select(s => s.Score),
                TotalResuts = searchResponse.Total
            };
            //get aggregations if any
            if (searchInfo.termDictionary != null)
            {
                foreach (var termInfo in searchInfo.termDictionary)
                {
                    var termKey = termInfo.Key;
                    var termVal = termInfo.Value;
                    var terms   = searchResponse.Aggregations.Terms(termKey);
                    if (terms != null)
                    {
                        var bucketDictionary = new Dictionary <string, AggregatorMetrics>();
                        foreach (var bucket in terms.Buckets)
                        {
                            var keyBucket = bucket.Key;
                            var agMetric  = new AggregatorMetrics();

                            foreach (var funcKey in bucket.Keys)
                            {
                                if (funcKey == string.Format("{0}_sum", termKey))
                                {
                                    var sum = bucket.Sum(funcKey);
                                    agMetric.Sum = (sum == null) ? null : sum.Value;
                                }
                                if (funcKey == string.Format("{0}_avg", termKey))
                                {
                                    var val = bucket.Average(funcKey);
                                    agMetric.Average = (val == null) ? null : val.Value;
                                }
                                if (funcKey == string.Format("{0}_min", termKey))
                                {
                                    var val = bucket.Min(funcKey);
                                    agMetric.Min = (val == null) ? null : val.Value;
                                }
                                if (funcKey == string.Format("{0}_max", termKey))
                                {
                                    var val = bucket.Max(funcKey);
                                    agMetric.Max = (val == null) ? null : val.Value;
                                }
                            }

                            var cnt = bucket.DocCount;
                            agMetric.Count = cnt;

                            bucketDictionary.Add(bucket.Key, agMetric);
                        }
                        _result.Aggregations.Grouped.Add(termKey, bucketDictionary);
                    }
                }
            }
            return(_result);
        }