private SearchDescriptor <DocumentElastic> GetSampleDescriptor(string seed, IEnumerable <string> tagIds, string tagField) { var sdesc = new SearchDescriptor <DocumentElastic>(); var queryContDesc = new QueryContainerDescriptor <DocumentElastic>(); var queryContainers = new List <QueryContainer>(); if (tagIds != null && tagIds.Any()) { var shouldDesc = new BoolQueryDescriptor <DocumentElastic>(); foreach (var batchTagIds in tagIds.Batch(1000)) { shouldDesc.Should(queryContDesc .Terms(t => t .Terms(batchTagIds) .Field(MapDocumentObjectName(tagField)))); } queryContainers.Add(queryContDesc.Bool(q => shouldDesc)); } queryContainers.Add( queryContDesc.FunctionScore(f => f.Functions(fun => fun.RandomScore(seed))) ); sdesc.Query(q => q.Bool(b => b.Must(queryContainers.ToArray()))); return(sdesc); }
public ScrolledSearchResult <DocumentElastic> Filter( string generalQuery, IEnumerable <string> tagIds, string tagField, int limit, string orderBy, bool isDescending, IEnumerable <string> interPretedFields, IEnumerable <string> documentObjectFieldNames, IEnumerable <string> returningDocumentObjectFields, IEnumerable <string> ids = null, DateTime?dateStart = null, DateTime?dateEnd = null, string shouldQuery = null) { var sdesc = new SearchDescriptor <DocumentElastic>(); var queryContDesc = new QueryContainerDescriptor <DocumentElastic>(); var queryContainers = new List <QueryContainer>(); if (!string.IsNullOrEmpty(generalQuery)) { var modifiedQuery = generalQuery; //replace the field names (because of the document_object) if (documentObjectFieldNames?.Any() == true) { modifiedQuery = PrefixQueryFields(modifiedQuery, documentObjectFieldNames); } if (interPretedFields != null && interPretedFields.Any()) { queryContainers.Add( queryContDesc.QueryString(q => q .Query(modifiedQuery) .Fields(interPretedFields.Select(f => MapDocumentObjectName(f)).ToArray()))); } else { queryContainers.Add( queryContDesc.QueryString(q => q.Query(modifiedQuery))); } } if (tagIds != null && tagIds.Any()) { var shouldDesc = new BoolQueryDescriptor <DocumentElastic>(); foreach (var batchTagIds in tagIds.Batch(1000)) { shouldDesc.Should(queryContDesc .Terms(t => t .Terms(batchTagIds) .Field(MapDocumentObjectName(tagField)))); } queryContainers.Add(queryContDesc.Bool(q => shouldDesc)); } if (ids != null && ids.Any()) { queryContainers.Add(queryContDesc.Ids(i => i.Values(ids))); } if (dateStart.HasValue) { queryContainers.Add( queryContDesc.DateRange(d => d .Field(DocumentElastic.ModifiedDateField) .GreaterThan(dateStart.Value))); } if (dateEnd.HasValue) { queryContainers.Add( queryContDesc.DateRange(d => d .Field(DocumentElastic.ModifiedDateField) .LessThanOrEquals(dateEnd.Value))); } // a REAL _should_ query, if we just add to the queryContainer then at least one of this condition must satisfied if (!string.IsNullOrEmpty(shouldQuery)) { var modifiedQuery = shouldQuery; //replace the field names (because of the document_object) if (documentObjectFieldNames?.Any() == true) { modifiedQuery = PrefixQueryFields(modifiedQuery, documentObjectFieldNames); } sdesc.Query(q => q.Bool(b => b .Must(queryContainers.ToArray()) .Should(sq => sq.QueryString(qs => qs.Query(modifiedQuery))))); } else { sdesc.Query(q => q.Bool(b => b.Must(queryContainers.ToArray()))); } if (!string.IsNullOrEmpty(orderBy)) { var fieldName = MapDocumentObjectName(orderBy); if (interPretedFields != null && interPretedFields.Contains(orderBy)) { fieldName += ".raw"; } sdesc.Sort(s => isDescending ? s.Descending(fieldName) : s.Ascending(fieldName)); } if (limit >= 0) { sdesc.Size(limit); } ApplyDocumentFieldFilter(sdesc, returningDocumentObjectFields); return(GetScrolled(sdesc)); }
public ISearchResponse <DocumentElastic> Search( AutoCompleteSettingsElastic autoCompleteSettings, SearchSettingsElastic searchSettings, string text, IEnumerable <string> documentObjectFieldNames, string tagField, IEnumerable <string> interPretedFields, FilterElastic defaultFilter, List <WeightElastic> defaultWeights ) { var sdesc = new SearchDescriptor <DocumentElastic>(); #region SEARCH if (searchSettings?.Count > 0) { var queryContDesc = new QueryContainerDescriptor <DocumentElastic>(); var queryContainers = new List <QueryContainer>(); var searchFields = searchSettings.SearchFieldList.Select(f => MapDocumentObjectName(f)).ToArray(); //FILTER if (searchSettings.UseDefaultFilter) { if (!string.IsNullOrEmpty(defaultFilter?.Query)) { var modifiedQuery = documentObjectFieldNames?.Any() == true? PrefixQueryFields(defaultFilter.Query, documentObjectFieldNames) : defaultFilter.Query; queryContainers.Add(queryContDesc.QueryString(q => q.Query(modifiedQuery))); } if (defaultFilter?.TagIdList?.Any() == true) { var shouldDesc = new BoolQueryDescriptor <DocumentElastic>(); foreach (var batchTagIds in defaultFilter.TagIdList.Batch(1000)) { shouldDesc.Should(queryContDesc .Terms(t => t .Terms(batchTagIds) .Field(MapDocumentObjectName(tagField)))); } queryContainers.Add(queryContDesc.Bool(q => shouldDesc)); } } if (!string.IsNullOrEmpty(searchSettings.Filter?.Query)) { var modifiedQuery = documentObjectFieldNames?.Any() == true? PrefixQueryFields(searchSettings.Filter.Query, documentObjectFieldNames) : searchSettings.Filter.Query; queryContainers.Add(queryContDesc.QueryString(q => q.Query(modifiedQuery))); } if (searchSettings.Filter?.TagIdList?.Any() == true) { var shouldDesc = new BoolQueryDescriptor <DocumentElastic>(); foreach (var batchTagIds in searchSettings.Filter.TagIdList.Batch(1000)) { shouldDesc.Should(queryContDesc .Terms(t => t .Terms(batchTagIds) .Field(MapDocumentObjectName(tagField)))); } queryContainers.Add(queryContDesc.Bool(q => shouldDesc)); } // MATCH TYPE SEARCH if (searchSettings.Type == (int)SDK.Net.Models.Enums.SearchTypeEnum.Match) { var mqd = new MultiMatchQueryDescriptor <DocumentElastic>() .Query(text) .Type(TextQueryType.BestFields) .CutoffFrequency(searchSettings.CutOffFrequency) .Fuzziness(searchSettings.Fuzziness < 0 ? Fuzziness.Auto : Fuzziness.EditDistance(searchSettings.Fuzziness)) .Fields(f => f.Fields(searchFields)) .Operator((Operator)searchSettings.Operator); queryContainers.Add(queryContDesc.MultiMatch(q => mqd)); } // QUERY(STRING) TYPE SEARCH if (searchSettings.Type == (int)SDK.Net.Models.Enums.SearchTypeEnum.Query) { var modifiedQuery = documentObjectFieldNames?.Any() == true? PrefixQueryFields(text, documentObjectFieldNames) : text; var qsd = new QueryStringQueryDescriptor <DocumentElastic>() .Query(text) //cutoff_frequency is not supported for querystring query //.CutoffFrequency(searchSettings.CutOffFrequency) .Fuzziness(searchSettings.Fuzziness < 0 ? Fuzziness.Auto : Fuzziness.EditDistance(searchSettings.Fuzziness)) .Fields(f => f.Fields(searchFields)) .DefaultOperator((Operator)searchSettings.Operator); queryContainers.Add(queryContDesc.QueryString(q => qsd)); } // WEIGHTS // a REAL _should_ query, if we just add to the queryContainer then at least one of this condition must satisfied var weights = new List <WeightElastic>(); if (searchSettings.UseDefaultWeights && (defaultWeights?.Any() == true)) { weights.AddRange(defaultWeights); } if (searchSettings.Weights?.Any() == true) { weights.AddRange(searchSettings.Weights); } if (weights.Any()) { var shouldQuery = string.Join(" ", weights.Select(k => $"({k.Query})^{k.Value}")); var modifiedQuery = documentObjectFieldNames?.Any() == true? PrefixQueryFields(shouldQuery, documentObjectFieldNames) : shouldQuery; sdesc.Query(q => q.Bool(b => b .Must(queryContainers.ToArray()) .Should(sq => sq.QueryString(qs => qs.Query(modifiedQuery))))); } else { sdesc.Query(q => q.Bool(b => b.Must(queryContainers.ToArray()))); } // ORDER if (!string.IsNullOrEmpty(searchSettings.Order?.OrderByField)) { var fieldName = MapDocumentObjectName(searchSettings.Order.OrderByField); if (interPretedFields != null && interPretedFields.Contains(searchSettings.Order.OrderByField)) { fieldName += ".raw"; } sdesc.Sort(s => (int)SortOrder.Descending == searchSettings.Order.OrderDirection ? s.Descending(fieldName) : s.Ascending(fieldName)); } // COUNT sdesc.Size(searchSettings.Count); ApplyDocumentFieldFilter(sdesc, searchSettings.ResponseFieldList.Select(f => MapDocumentObjectName(f))); } else { sdesc.Size(0); } #endregion #region SUGGEST if (autoCompleteSettings?.Count > 0) { var psgd = new PhraseSuggesterDescriptor <DocumentElastic>() .Field(DocumentElastic.TextField) .Size(autoCompleteSettings.Count) //.RealWordErrorLikelihood(0.95), 0.95 is the default value .Confidence(autoCompleteSettings.Confidence) .MaxErrors(autoCompleteSettings.MaximumErrors) .DirectGenerator(dg => dg .Field(DocumentElastic.TextField) .SuggestMode(SuggestMode.Always) .MinWordLength(3) .MinDocFrequency(3) .Size(1)) .Collate(c => c .Prune() .Query(q => q //unfortunately Params is not working here so had to hack the text field like this .Inline($"{{\"match\": {{\"{DocumentElastic.TextField}\" : {{\"query\": \"{{{{suggestion}}}}\", \"operator\": \"and\"}}}}}}") ) ) .Text(text); sdesc.Suggest(s => s.Phrase(SuggestName, p => psgd)); } #endregion var resp = Client.Search <DocumentElastic>(sdesc); ResponseValidator(resp); return(resp); }