如果我有一个复杂的文档在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/