Example #1
0
        IEnumerable <object> UserQuery(API.Common.Models.SearchRequest searchRequest)
        {
            if (searchRequest.KeywordQuery != null)
            {
                yield return(new
                {
                    wildcard = new
                    {
                        name = new
                        {
                            boost = 1.1,
                            value = $"*{searchRequest.KeywordQuery}*"
                        }
                    }
                });

                yield return(new
                {
                    match = new
                    {
                        content = new
                        {
                            query = searchRequest.KeywordQuery
                        }
                    }
                });
            }

            if (searchRequest.NativeQuery != null)
            {
                yield return new
                       {
                           query_string = new
                           {
                               query = searchRequest.NativeQuery
                           }
                       }
            }
            ;
        }

        async Task <ISearchResults> OldSearch(
            string[] securityIdentifiers,
            API.Common.Models.SearchRequest searchRequest)
        {
            Logger.LogInformation($"Search {searchRequest.FolderIdentifier} \"{searchRequest}\"");

            var identifiers = "_all " + string.Join(" ", securityIdentifiers ?? new string[0]);

            int FacetLimit = 10;

            SearchDescriptor <Document> searchDescriptor = null;
            var sortField = searchRequest.Paging.SortField;

            searchDescriptor = new SearchDescriptor <Document>()
                               .Query(q => q
                                      .Bool(b => b
                                            .MinimumShouldMatch(1)
                                            .Filter(
                                                f => DoFolderFiltering(f, searchRequest),
                                                f => DoSecurity(f, securityIdentifiers),
                                                f => DoFacetFiltering(f, searchRequest.Filters)
                                                )
                                            .Should(DoQueries(q, searchRequest))
                                            )
                                      )
                               .Highlight(h => h
                                          .PreTags("<em>")
                                          .PostTags("</em>")
                                          .Fields(fs => fs
                                                  .Field(p => p.Content)
                                                  .Type(HighlighterType.Fvh)
                                                  .BoundaryMaxScan(50)
                                                  .NumberOfFragments(3)
                                                  )
                                          )
                               .From(searchRequest.Paging.PageIndex * searchRequest.Paging.PageSize)
                               .Size(searchRequest.Paging.PageSize == 0
                    ? 500
                    : searchRequest.Paging.PageSize)
                               .Sort(ss => ss
                                     .Field(f =>
            {
                f.Order(searchRequest.Paging.IsAscending
                            ? SortOrder.Ascending
                            : SortOrder.Descending);

                switch (searchRequest.Paging.SortField)
                {
                case "name":
                    f.Field(ff => ff.Name);
                    break;

                default:
                    f.Field("_score");
                    f.Descending();
                    break;
                }

                return(f);
            })
                                     )
                               .Aggregations(aggs => aggs
                                             .Nested("facet_strings", n => n
                                                     .Path(p => p.FacetStrings)
                                                     .Aggregations(aa => aa
                                                                   .Terms("facet_name", t => t
                                                                          .Field(new Field("facets.name"))
                                                                          .Aggregations(a2 => a2
                                                                                        .Terms("facet_value", t2 => t2
                                                                                               .Field(new Field("facets.value"))
                                                                                               .Size(FacetLimit)
                                                                                               )
                                                                                        )
                                                                          )
                                                                   )
                                                     )
                                             )
            ;


            string debugQuery = SerializeNESTObject(searchDescriptor);

            Logger.LogDebug($"Search Query: (index: {IndexName})\n {debugQuery}");

            var results = await client.SearchAsync <Document>(searchDescriptor);

            //Logger.LogDebug($"Raw Results: {SerializeNESTObject(results)}");

            var searchResults = new SearchResults
            {
                Rows = results.Hits.Select(d => new SearchResult
                {
                    FileIdentifier = new FileIdentifier
                    {
                        OrganizationKey = d.Source.OrganizationKey,
                        FolderKey       = d.Source.FolderKey,
                        FileKey         = d.Source.FileKey
                    },

                    Name      = d.Source.Name,
                    Extension = d.Source.Extension,
                    MimeType  = d.Source.MimeType,

                    Metadata = d.Source.Metadata,

                    Created    = d.Source.Created,
                    Modified   = d.Source.Modified,
                    Highlights = d.Highlights.SelectMany(h => h.Value.Highlights).ToArray(),

                    Fields = d.Source.Fields
                }),

                TotalMatches = results.Total,
                DebugQuery   = debugQuery
            };

            var facetModels = new List <FacetModel>();

            if ((results.Aggregations.FirstOrDefault(a => a.Key == "facet_strings")
                 .Value as SingleBucketAggregate)
                ?.FirstOrDefault()
                .Value is BucketAggregate facets)
            {
                foreach (var facet in facets.Items.OfType <KeyedBucket <object> >())
                {
                    var model = new FacetModel
                    {
                        Name = facet.Key.ToString()
                    };

                    var values = new List <FacetValue>();
                    model.Values = values;

                    foreach (var container in facet.Values.OfType <BucketAggregate>())
                    {
                        foreach (var facetValue in container.Items.OfType <KeyedBucket <object> >())
                        {
                            values.Add(new FacetValue
                            {
                                Value = facetValue.Key.ToString(),
                                Count = facetValue.DocCount
                            });
                        }

                        if (model.Values.Any() && container.SumOtherDocCount == 0)
                        {
                            if (model.Values.Count() == 1 &&
                                model.Values.First().Count == results.Total)
                            {
                                // this is a single facet describing all
                                // results. it doesn't further differentiate the resultset.

                                // skip it
                            }
                            else
                            {
                                facetModels.Add(model);
                            }
                        }
                    }
                }
            }
            searchResults.Facets = facetModels;

            return(searchResults);
        }
Example #2
0
        async Task <ISearchResults> ISearch.Search(
            string[] securityIdentifiers,
            API.Common.Models.SearchRequest searchRequest)
        {
            var query = new
            {
                from = searchRequest.Paging.PageIndex * searchRequest.Paging.PageSize,
                size = searchRequest.Paging.PageSize,
                sort = new[]
                {
                    new { _score = new { order = "desc" } }
                },
                highlight = new
                {
                    pre_tags  = new[] { "<em>" },
                    post_tags = new[] { "</em>" },
                    fields    = new
                    {
                        content = new
                        {
                            number_of_fragments = 3,
                            boundary_max_scan   = 50,
                            type = "fvh"
                        }
                    }
                },
                aggs = new
                {
                    facet_strings = new
                    {
                        nested = new { path = "facets" },
                        aggs   = new
                        {
                            facet_name = new
                            {
                                terms = new { field = "facets.name" },
                                aggs  = new
                                {
                                    facet_value = new { terms = new { field = "facets.value", size = 10 } }
                                }
                            }
                        }
                    }
                },
                _source = new[] {
                    "uniqueKey",
                    "indexed",
                    "organizationKey",
                    "folderKey",
                    "fileKey",
                    "type",
                    "name",
                    "extension",
                    "mimeType",
                    "created",
                    "modified",
                    "mimeType",
                    "fields",
                    "metadata",
                    "facets"
                },
                query = new
                {
                    @bool = new
                    {
                        should = UserQuery(searchRequest),
                        filter = OrganizationAndFolderFilter(searchRequest.OrganizationIdentifier, searchRequest.FolderIdentifier)
                                 .Append(SecurityFilters(securityIdentifiers))
                                 .Append(NestedFacetFilters(searchRequest)),
                        minimum_should_match = 1
                    }
                }
            };


            var queryJSON      = JsonConvert.SerializeObject(query);
            var searchResponse = await lowLevelClient.SearchAsync <StringResponse>(IndexName, PostData.String(queryJSON));

            var deserialized = JsonConvert.DeserializeObject <SearchResposne>(searchResponse.Body);

            var searchResults = new SearchResults
            {
                Rows = deserialized.Hits.Hits.Select(d => new SearchResult
                {
                    FileIdentifier = new FileIdentifier
                    {
                        OrganizationKey = d._Source.OrganizationKey,
                        FolderKey       = d._Source.FolderKey,
                        FileKey         = d._Source.FileKey
                    },

                    Name      = d._Source.Name,
                    Extension = d._Source.Extension,
                    MimeType  = d._Source.MimeType,

                    Metadata = d._Source.Metadata,

                    Created    = d._Source.Created,
                    Modified   = d._Source.Modified,
                    Highlights = d.Highlight?.SelectMany(h => h.Value).ToArray(),

                    Fields = d._Source.Fields.Where(f => !String.IsNullOrWhiteSpace(f.Value)).ToDictionary(f => f.Key, f => f.Value)
                }),

                TotalMatches = deserialized.Hits.Total,
                DebugQuery   = queryJSON
            };

            var facetModels = new List <FacetModel>();

            foreach (var facet in deserialized.Aggregations.Facet_Strings.Facet_Name.Buckets)
            {
                var model = new FacetModel
                {
                    Name = facet.Key.ToString()
                };

                var values = new List <FacetValue>();
                model.Values = values;

                foreach (var facetValue in facet.Facet_Value.Buckets)
                {
                    values.Add(new FacetValue
                    {
                        Value = facetValue.Key.ToString(),
                        Count = facetValue.Doc_Count
                    });
                }

                if (model.Values.Any() && facet.Facet_Value.Sum_Other_Doc_Count == 0)
                {
                    if (model.Values.Count() == 1 &&
                        model.Values.First().Count == deserialized.Hits.Total)
                    {
                        // this is a single facet describing all
                        // results. it doesn't further differentiate the resultset.

                        // skip it
                    }
                    else
                    {
                        facetModels.Add(model);
                    }
                }
            }
            searchResults.Facets = facetModels;

            return(searchResults);
        }