NEST - 返回部分文档

Selecting fields to return

Version:5.x

英文原文地址:Selecting fields to return

有时候,不需要让 Elasticsearch 返回查询的文档中的全部字段。举个栗子,当展示最近发布的博客时,在查找到最新的帖子后只需要返回博客的标题。

有两种方法可以用来返回文档中的部分字段,即部分文档(我们使用这个术语来描述)。一个是 stored fields ,另一个是 source filtering ,两者在工作方式上有很大的不同。

Stored fields

索引文档时,默认情况下,Elasticsearch 将最初发送的 JSON 文档存储在一个名叫 _source 的特殊字段中。从搜索查询返回的文档是 Elasticsearch 返回的每个命中的 _source 字段的具体化。

还可以在映射的时候使用 store ,把 JSON 文档中的字段分别存储在 Elasticsearch 中。为什么要这么做呢?你可能禁用了 _source 以便不存储源文档,并选择存储特定的字段。另一种可能性是,_source 包含一个具有较大值的字段(例如一篇博客的正文),但通常只需要另一个字段(例如博客的标题)。这种情况下,我们不想为了得到一个小字段而反序列化整个 _source

重要:选择禁用类型映射中的 _source ,意味着不存储发送到 Elasticsearch 的原始 JSON 文档,因此永远无法检索原始文档。虽然这样做可以节省磁盘空间,但与此同时某些功能(如 Reindex API 或者 highlighting)也将无法正常工作。

一定要认真考虑,禁用源文档是否真的符合你的需求。

以这种方式存储字段时,可以使用搜索请求的 .StoredFields() 方法来指定需要返回的字段

var searchResponse = client.Search<Project>(s => s
    .StoredFields(sf => sf
        .Fields(
            f => f.Name,
            f => f.StartedOn,
            f => f.Branches
        )
    )
    .Query(q => q
        .MatchAll()
    )
);

使用响应对象的 .Fields 属性检索它们

foreach (var fieldValues in searchResponse.Fields)
{
    var document = new 
    {
        Name = fieldValues.ValueOf<Project, string>(p => p.Name),
        StartedOn = fieldValues.Value<DateTime>(Infer.Field<Project>(p => p.StartedOn)),
        Branches = fieldValues.Values<Project, string>(p => p.Branches.First())
    };
}

这种方法在单独存储字段时有效。然而,更常见的情况是从 _source 中返回选择的字段。这便是 source filtering 的由来。

Source filtering

搜索查询时使用 source filtering 可以返回文档的部分字段

var searchResponse = client.Search<Project>(s => s
    .Source(sf => sf
        .Includes(i => i 
            .Fields(
                f => f.Name,
                f => f.StartedOn,
                f => f.Branches
            )
        )
        .Excludes(e => e 
            .Fields("num*") 
        )
    )
    .Query(q => q
        .MatchAll()
    )
);

在请求中指定了源过滤之后,响应对象的 .Documents 就只包含部分文档了、

var partialProjects = searchResponse.Documents;

你也可以从查询中完全排除 _source

searchResponse = client.Search<Project>(s => s
    .Source(false)
    .Query(q => q
        .MatchAll()
    )
);
posted @ 2018-01-21 13:29  祁去尘  阅读(791)  评论(0编辑  收藏  举报