コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
 private BoolQueryDescriptor <FTPEntry> _mustHaveParents(BoolQueryDescriptor <FTPEntry> descriptor, bool HaveParents)
 {
     if (HaveParents)
     {
         return(descriptor.Must(m => m
                                .Exists(e => e
                                        .Field(f => f.Parent)
                                        )
                                ));
     }
     else
     {
         return(descriptor.MustNot(mn => mn
                                   .Exists(e => e
                                           .Field(f => f.Parent)
                                           )
                                   ));
     }
 }
コード例 #4
0
        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);
        }
コード例 #5
0
        private static BoolQueryDescriptor <DocumentDM> ExactQuery(DocumentDM doc)
        {
            var boolQuery = new BoolQueryDescriptor <DocumentDM>();

            //ex
            boolQuery.Must(mu => mu
                           .Match(m => !doc.Subject[0].Equals('?') ? m
                                  .Field(f => f.Subject)
                                  .Query(doc.Subject) : m
                                  ), mud => mud
                           .Match(m => !doc.Predicate[0].Equals('?') ? m
                                  .Field(f => f.Predicate)
                                  .Query(doc.Predicate) : m
                                  ),
                           mud => mud
                           .Match(m => !doc.Obj[0].Equals('?') ? m
                                  .Field(f => f.Obj)
                                  .Query(doc.Obj) : m
                                  )

                           );
            return(boolQuery);
        }
コード例 #6
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public async Task <ISearchResponse <T> > ToListAsync()
        {
            SearchDescriptor <T>    selector  = new SearchDescriptor <T>();
            BoolQueryDescriptor <T> boolQuery = new BoolQueryDescriptor <T>();

            if (_mustSelector.Count > 0)
            {
                boolQuery.Must(_mustSelector);
            }
            if (_mustNotSelector.Count > 0)
            {
                boolQuery.MustNot(_mustNotSelector);
            }
            if (!string.IsNullOrWhiteSpace(IndexName))
            {
                selector.Index(IndexName);
            }
            selector = selector.Query(q => q.Bool(b => boolQuery)).From(SkipCount ?? 0);
            if (TakeCount > 0)
            {
                selector.Size(TakeCount.Value);
            }
            if (sortor != null)
            {
                selector.Sort(sortor);
            }
            var response = await _searchContext.Context.SearchAsync <T>(selector);

            if (!response.IsValid)
            {
                _searchContext.Logger.LogError($"[Success:{response.ApiCall.Success}]\t{response.ApiCall.Uri}");
                _searchContext.Logger.LogError(response.ApiCall.DebugInformation);
                _searchContext.Logger.LogError(response.ApiCall.OriginalException?.Message);
            }
            return(response);
        }
コード例 #7
0
#pragma warning restore IDE0039 // Use local function

            static IBoolQuery TestBoolQuery(BoolQueryDescriptor <Person> b) => b.Name("thing");
コード例 #8
0
        private DataTable ElasticSearch(DocumentDM doc)
        {
            DataTable table = new DataTable();

            ConnectionSettings   connectionSettings;
            ElasticClient        elasticClient;
            StaticConnectionPool connectionPool;

            var nodes = new Uri[]
            {
                new Uri("http://localhost:9200/"),
            };

            connectionPool     = new StaticConnectionPool(nodes);
            connectionSettings = new ConnectionSettings(connectionPool);
            elasticClient      = new ElasticClient(connectionSettings);
            //var searchResult = elasticClient.Search<DocumentDM>(s => s
            //                    .Size(500)
            //                    .Index("*")
            //                    .Query(q => q
            //                        .MultiMatch(m => m
            //                            //get fields that are not variables
            //                            .Fields(doc.GetTripleFields().Split(' ').ToList<string>().Select(x => new Field(x)).ToArray())
            //                            //.Fields(f=> f
            //                            //        .Field("subject")
            //                            //        .Field("predicate")
            //                            //        .Field("object"))
            //                            //get text that is not variables
            //                            .Query(doc.GetTripleText())
            //                        )
            //                    )
            //                );

            BoolQueryDescriptor <DocumentDM> boolQuery = ExactQuery(doc);

            var searchResult = elasticClient.Search <DocumentDM>(s => s
                                                                 .Size(500)
                                                                 .Index("*")
                                                                 .Query(q => q.Bool(b => boolQuery))
                                                                 );

            table.Columns.Add("subject", typeof(String));
            table.Columns.Add("predicate", typeof(String));
            table.Columns.Add("object", typeof(String));
            table.Columns.Add("score", typeof(String));
            table.Columns.Add("index", typeof(String));
            table.Columns.Add("invisible", typeof(String));
            for (int i = 0; i < searchResult.Documents.Count; i++)
            {
                var           subject   = searchResult.Documents.ElementAt(i).Subject;
                var           predicate = searchResult.Documents.ElementAt(i).Predicate;
                var           obj       = searchResult.Documents.ElementAt(i).Obj;
                var           score     = searchResult.HitsMetadata.Hits.ElementAt(i).Score;
                var           index     = searchResult.HitsMetadata.Hits.ElementAt(i).Index;
                StringBuilder sb        = new StringBuilder();
                sb.Append(subject);
                sb.Append(" ");
                sb.Append(predicate);
                sb.Append(" ");
                sb.Append(obj);
                sb.Append(" ");
                sb.Append(score);
                sb.Append(" ");
                sb.Append(index);
                var row = new object[] { subject, predicate, obj, score, index, sb.ToString() };
                table.Rows.Add(row);
            }

            return(table);
            //if (!doc.Subject[0].Equals('?'))
            //{
            //    var subjectResponse = elasticClient.Search<DocumentDM>(sd => sd
            //                        .Index("*")
            //                        .Size(1000)
            //                        .Query(q => q
            //                            .Match(m => m.Field("subject").Query(doc.Subject)
            //                            )));
            //}

            //if (!doc.Predicate[0].Equals('?'))
            //{
            //    var predicateResponse = elasticClient.Search<DocumentDM>(sd => sd
            //                    .Index("*")
            //                    .Size(1000)
            //                    .Query(q => q
            //                        .Match(m => m.Field("predicate").Query(doc.Predicate)
            //                        )));
            //}

            //if (!doc.Obj[0].Equals('?'))
            //{
            //    var objectResponse = elasticClient.Search<DocumentDM>(sd => sd
            //                    .Index("*")
            //                    .Size(1000)
            //                    .Query(q => q
            //                        .Match(m => m.Field("object").Query(doc.Obj)
            //                        )));
            //}
        }
コード例 #9
0
        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));
        }
コード例 #10
0
        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);
        }
コード例 #11
0
        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));
            }
        }