NEST项目会在elasticsearch还是在客户端?

Will NEST project in elasticsearch or in the client?

如果我在 elasticsearch 中索引了一个复杂的文档并使用 DTO 对其进行查询,在将数据发送到 C# 客户端之前,是否将 DTO 所需字段的投影应用到 elasticsearch 中,或者完整的源是已发送,C# 将使用它来补充 DTO?

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

基本上,我需要知道我是否可以简单地请求一个 TDto 而不必担心索引的较大 ComplexDocument 的数据量,或者我是否必须指定 Source inclusion/exclusion 在 searchRequest 中获得最佳性能。

默认情况下,Elasticsearch 会为每次搜索命中发回完整的 _source 文档。可以用source filtering

指定_source到include/exclude的哪些字段
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"]
    }
}

或者你可以要求根本不 return _source

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

使用源过滤,_source 的存储字段在 Elasticsearch 端被完全读取,并应用过滤。这通常很好,但是如果 _source 是一个 巨大的 文档,并且您只想 return 字段的子集来响应搜索,您可能决定改用 stored fields

顾名思义,存储字段是单独存储到 _source 的字段(通过在其映射中指定 store:true)并且可以在搜索响应中 returned

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);
}

存储的字段在每次点击时 return 编辑在 "fields" 属性 中。

If I have a complex document indexed in elasticsearch and query it using a DTO, will a projection for the fields required by the DTO be applied in elasticsearch, before sending the data to the C# client or will the full source be sent, and C# will use that to hydrate the DTO?

总而言之,Elasticsearch 将 return 完整 _source,NEST 会将 _source 中的匹配属性映射到 DTO 的属性。巢 maps camel case properties in JSON to the POCO properties by default。如果您想通过线路传输更少的数据,请查看源过滤。您可能会将功能打包为仅在请求中包含 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"]
    }
}