c# - NEST是否会在Elasticsearch或客户端中进行投影?

标签 c# performance elasticsearch nest dto

如果我有一个复杂的文档在Elasticsearch中建立索引并使用DTO对其进行查询,那么在将数据发送到C#客户端之前,将在Elasticsearch中应用DTO所需字段的投影,还是将完整的源发送出去,并且C#将用它来水合DTO吗?
var response = await elasticClient.SearchAsync<TDto>(searchRequest);
基本上,我需要知道是否可以简单地请求TDto,而不必担心被索引的较大ComplexDocument的数据量,或者是否必须在Source中指定searchRequest包含/排除才能获得最佳性能。

最佳答案

默认情况下,Elasticsearch将针对每个搜索命中发送完整的_source文档。您可以指定source filtering包含/排除的_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)
);

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

顾名思义,存储的字段是与_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"属性返回。

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将返回完整的_source,而NEST会将_source中的匹配属性映射到DTO的属性。 NEST 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"]
    }
}

关于c# - NEST是否会在Elasticsearch或客户端中进行投影?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61320740/

相关文章:

performance - hadoop YARN性能:在群集上运行wordCount示例非常慢

C# 嵌套、 Elasticsearch : update and add to a field that is a list

c# - Linq 连接上的 System.OutOfMemoryException

c# - 像编辑 ListViewItems 一样编辑 ListView Group Headers

c++ - 比 C++ 更快的语言

ios - SpriteKit : Collisions with 300 nodes, FPS 非常低

c# - ElasticSearch和NEST查询问题

elasticsearch - 如何仅使用Shield访问仪表板选项卡以监控kibana中的图形?

c# - 获取匿名类型的读/写属性

c# - 如何在用户未注销的情况下关闭浏览器时终止 session