Будет ли проект NEST в эластичном поиске или в клиенте? - PullRequest
0 голосов
/ 20 апреля 2020

Если у меня есть сложный документ, проиндексированный вasticsearch, и запросить его с помощью DTO, будет ли проекция для полей, требуемых DTO, применена вasticsearch до отправки данных клиенту C# или будет полный источник отправлено, и C# будет использовать это для увлажнения DTO?

var response = await elasticClient.SearchAsync<TDto>(searchRequest);

В основном мне нужно знать, могу ли я просто попросить TDto и не беспокоиться о данных объем большего ComplexDocument, который был проиндексирован, или если мне нужно указать Source включение / исключение в searchRequest, чтобы получить наилучшую производительность.

1 Ответ

1 голос
/ 21 апреля 2020

По умолчанию Elasticsearch отправляет обратно полный документ _source для каждого поискового попадания. Вы можете указать, какие поля _source включить / исключить с фильтрацией источника

var client = new ElasticClient();

var searchResponse = client.Search<ComplexDocument>(s => s
    .Source(sf => sf
        .Includes(i => i
            .Field(f => f.Path)
            .Field(f => f.Content)
        )
        .ExcludeAll()
    )
);

foreach(var source in searchResponse.Documents)
{
    var path = source.Path;
}

, которая отправляет

{
    "_source": {
        "excludes": ["*"],
        "includes": ["path", "content"]
    }
}

Или вы можете попросить не возвращать _source на всех

var searchResponse = client.Search<ComplexDocument>(s => s
    .Source(false)
);

При исходной фильтрации поле хранения для _source полностью считывается со стороны Elasticsearch и применяется фильтрация. Обычно это нормально, но если _source является огромным документом, и вы когда-либо захотите вернуть подмножество полей в ответ на поиск, вы можете решить использовать сохраненные поля вместо.

Как следует из названия, сохраненные поля являются полями, которые хранятся отдельно в _source (указав store:true в их отображении) и могут быть возвращены в ответе на поиск

var searchResponse = client.Search<ComplexDocument>(s => s
    .StoredFields(f => f
        .Field(ff => ff.Path)
    )
);

foreach(var fields in searchResponse.Fields)
{
    var path = fields.ValueOf<ComplexDocument, string>(f => f.Path);
}

Сохраненные поля возвращаются в свойстве "fields" при каждом попадании.

Если у меня есть сложный документ, проиндексированный вasticsearch, и запросить его с помощью DTO, будет ли применяться проекция для полей, требуемых DTO, в asticsearch, перед отправкой данных клиенту C# или будет отправлен полный источник, и C# будет использовать это для увлажнения DTO?

В итоге Elasticsearch вернет полный _source и NEST будут сопоставлять соответствующие свойства в _source со свойствами DTO. NEST сопоставляет свойства корпуса верблюда в JSON со свойствами POCO по умолчанию . Если вы хотите передавать меньше по проводам, взгляните на фильтрацию источников. Возможно, вы могли бы обернуть функциональность, чтобы включить в запрос только поля в DTO в качестве метода расширения для SearchDescriptor<TInferDocument>

public class ComplexDocument
{
    public int Id { get; set; }
    public string Path { get; set; }
    public string Content { get; set; }
    public Attachment Attachment { get; set; }
}

public class SimpleDTO
{
    public string Path { get; set; }
}

public static class SearchDescriptorExtensions
{
    public static SearchDescriptor<TInferDocument> SourceIncludesDto<TInferDocument, TDocument>(this SearchDescriptor<TInferDocument> descriptor) 
        where TInferDocument : class
        where TDocument : class
        {
            // TODO: cache this :)
            Fields fields = typeof(TDocument).GetProperties();

            return descriptor.Source(s => s
                .Includes(f => f
                    .Fields(fields)
                )
            );
        }
}

ISearchResponse<SimpleDTO> searchResponse = 
    client.Search<ComplexDocument, SimpleDTO>(s => s
        .SourceIncludesDto<ComplexDocument, SimpleDTO>()
    );

отсылок

{
    "_source": {
        "includes": ["path"]
    }
}
...