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)); }
/// <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); }