Получение результатов поиска с группировкой по типу документа в один вызов (NEST, AWS Elasticsearch) - PullRequest
1 голос
/ 23 сентября 2019

все.Заранее благодарю за помощь!

Я запрашиваю выгружаемые данные из AWS Elasticsearch, используя NEST.Каждый документ в индексе AWS Elasticsearch имеет тип контента (Тема, Вопрос и Видео).В ответ я получаю список документов для текущей страницы и их итоговые результаты.Все в порядке с этим.

Итак, вопрос: как я могу получить какую-то карту ответов, а также результаты поиска за один звонок?

Я имею в виду, например, вот мой ответ:Док 1 - ТемаДок 2 - ТемаДок 3 - ВидеоДок 4 - ВопросДок 5 - ВидеоВсего результатов: 5 шт.

В дополнение к этому, я хотел бы получить следующую «карту»:Тема - 2 предметаВидео - 2 предметаВопрос - 1 предмет

Можно ли это сделать за один запрос?Или как это можно сделать несколькими запросами?Может быть, NEST Aggregations является чем-то вроде необходимого решения, но, похоже, у него нет логики «подсчета»

Это запрос поиска для данных с подкачкой и некоторых моделей:

public class Document
{
    public int DocumentId  { get; set; }
    public ContentType ContentType { get; set; }
    public DateTime UpdatedOn { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
}

public virtual DocumentSearchResponse FullTextSearch(DocumentSearchParams searchParams)
{
    var resultsSearchRequest = _elasticClient.Search<Document>(s => s.Index("some_index")
                                            .Query(q => q.Term(t => t.Field(f => f.DocumentId).Value(searchParams.ContentId))
                                                     && q.Terms(t => t.Field(f => f.ContentType).Terms(searchParams.GetContentTypesIds()))
                                                     && q.MultiMatch(m => m.Fields(fs => fs.Field(f => f.Title).Field(f => f.Description))
                                                         .Query(searchParams.SearchValue)
                                                         .Type(TextQueryType.MostFields)))
                                            .Sort(ss => ss.Descending(f => f.UpdatedOn))
                                            .From((searchParams.PageNumber - 1) * searchParams.PageSize)
                                            .Size(searchParams.PageSize));

    // Is valid check
    return new DocumentSearchResponse
    {
        PageResults = _searchResponseHelper.ToPageResults(resultsSearchRequest.Documents),
        PageResultsMap = new Dictionary<ContentType, int>, // <- here
        TotalResultsCount = resultsSearchRequest.HitsMetadata.Total.Value
    };
}

1 Ответ

0 голосов
/ 27 сентября 2019

Итак, я выяснил это.Может быть, кто-то найдет это полезным.То, что мне было нужно, это «Агрегации».Добавление следующей строки перед .Form и .Size сгруппирует результаты поиска по указанному полю:

.Aggregations(a => a.Terms("contentType", t => t.Field(f => f.ContentType)))
.Query(...)
.Form(...)
.Size(...)

Чтобы обработать результат в нужном мне словаре, добавьте следующее (searchAggregations is searchResponse.Aggregations):

public Dictionary<ContentType, long> ToPageResultsMap(AggregateDictionary searchAggregations)
{
    var pageResultsMap = new Dictionary<ContentType, long>();

    var buckets = searchAggregations.Terms(DataConsts.SearchContentTypeDocFieldName).Buckets;

    foreach (var item in buckets)
    {
        if(int.TryParse(item.Key, out int contentType))
        {
            pageResultsMap.Add((ContentType)contentType, item.DocCount.HasValue ? item.DocCount.Value : 0);
        }
    }

    return pageResultsMap;
}
...