private static Func <QueryContainerDescriptor <TIndexItem>, QueryContainer> CreateQuery(ISearchArgs searchArgs, Collection <TextSearchField <TIndexItem> > textSearchFields, ICollection <Func <QueryContainerDescriptor <TIndexItem>, QueryContainer> > filters = null) { var boolQueryDescriptor = new BoolQueryDescriptor <TIndexItem>(); if (!string.IsNullOrWhiteSpace(searchArgs.SearchText)) { if (textSearchFields == null || !textSearchFields.Any()) { throw new ElasticSearchException("At least one text field need to be specified for text search"); } var textSearch = WildcardTextSearch(searchArgs.SearchText, textSearchFields); boolQueryDescriptor.Must(textSearch); } filters ??= new Collection <Func <QueryContainerDescriptor <TIndexItem>, QueryContainer> >(); boolQueryDescriptor.Filter(filters); QueryContainer Query(QueryContainerDescriptor <TIndexItem> q) => q.Bool(b => boolQueryDescriptor); return(Query); }
public static BoolQueryDescriptor <T> Filter <T>( this BoolQueryDescriptor <T> value, object filter, IDictionary <Type, Func <object, string> > filterValueFormatters = null) where T : class { if (filter == null) { return(value); } var mustQueries = FilterLogic.GenerateMustQueriesFromFilter <T>(filter, filterValueFormatters); if (mustQueries.Any()) { return(value.Filter(mustQueries)); } return(value); }
public override async Task <IEnumerable <ArtifactSearchResult> > GetSemanticSearchSuggestions(SearchEngineParameters searchEngineParameters) { try { var index = await SemanticSearchRepository.GetSemanticSearchIndex(); if (String.IsNullOrEmpty(index)) { // Returning empty results when index has not been created yet. return(new List <ArtifactSearchResult>()); } PerformIndexHealthCheck(index); // Setting default index name on the connection, otherwise the search request will fail _elasticClient.ConnectionSettings.DefaultIndices.Clear(); _elasticClient.ConnectionSettings.DefaultIndices.Add(typeof(SemanticSearchItem), index); var searchText = await SemanticSearchRepository.GetSemanticSearchText(searchEngineParameters.ArtifactId, searchEngineParameters.UserId); // Create the bool query descripter that just searchs for the searchText we constructed var boolQueryDescriptor = new BoolQueryDescriptor <SemanticSearchItem>(); boolQueryDescriptor.Must(GetMoreLikeThisQuery(searchText)); // Dont return back result for the current artifact id we're searching against boolQueryDescriptor.MustNot(GetArtifactIdMatchQuery(searchEngineParameters.ArtifactId)); // If not instance admin, use the list of accessible project ids to filter out, otherwise no need to filter if (!searchEngineParameters.IsInstanceAdmin) { boolQueryDescriptor.Filter(GetContainsProjectIdsQuery(searchEngineParameters.AccessibleProjectIds)); } // Creates the search descriptor var searchDescriptor = new SearchDescriptor <SemanticSearchItem>(); searchDescriptor.Index(index).Size(searchEngineParameters.PageSize).Query(q => q.Bool(b => boolQueryDescriptor)); var results = await _elasticClient.SearchAsync <SemanticSearchItem>(searchDescriptor); var hits = results.Hits; var itemIds = new List <int>(); hits.ForEach(a => { int output; if (Int32.TryParse(a.Id, out output)) { itemIds.Add(output); } }); // parse the artifact ids into a artifactsearchresult to return to the caller return(await GetArtifactSearchResultsFromItemIds(itemIds.Distinct().ToList(), searchEngineParameters.UserId)); } catch (Exception ex) { if (ex is ElasticsearchConfigurationException) { throw; } throw new ElasticsearchException(I18NHelper.FormatInvariant("Elastic search failed to process search. Exception:{0}", ex)); } }