如何将地图转换为 SearchSourceBuilder?

How do I convert a map to a SearchSourceBuilder?

在 Elasticsearch 2.x 中,我们使用 source(Map) 初始化 SearchRequest 的源:

SearchRequest searchRequest = new SearchRequest();
searchRequest.source((Map<?,?>) request.get("search_request"));

在 Elasticsearch 5 中,所有 source(...) 方法都消失了,取而代之的是一个 SearchSourceBuilder 方法。记录了这么多。

但是我究竟如何将 Map 转换为 SearchSourceBuilder?那里似乎没有任何有用的工厂方法,我已经搜索了其他采用 Map 的方法,但似乎没有任何东西跳出来。

您强调的问题 has been reported but this is not possible anymore because of this

您可以阅读 the full story 与这一重大变化相关的内容,但用两个词来说,在 ES 2.x 中,协调节点(即接收查询的节点)会将查询的解析委托给每个分片不仅浪费资源(主要是 CPU 周期),而且还有一些其他缺点,因为无法在一个地方优化查询。

在 ES 5 中,他们决定由协调节点进行一次解析,然后将解析后的查询发送到每个分片。如果您阅读我链接到的那个博客 post,您会发现这应该是一个很大的改进。当然,这意味着您不能再使用 SearchRequest.source(Map) 方法。

更新

source(Map) 方法的 original source code 看起来像这样:

public SearchRequest source(Map source) {
    try {
        XContentBuilder builder = XContentFactory.contentBuilder(Requests.CONTENT_TYPE);
        builder.map(source);
        return source(builder);
    } catch (IOException e) {
        throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e);
    }
}

没有什么能阻止您在应用程序代码中使用该代码来执行转换。

我还没有测试过,但是你应该可以像这样创建一个 SearchSourceBuilder

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

// from Map to XContent
XContentBuilder builder = ... // see above
// from XContent to JSON
String json = new String(builder.getBytes(), "UTF-8");
// use JSON to populate SearchSourceBuilder
JsonXContent parser = createParser(JsonXContent.jsonXContent, json));
sourceBuilder.parseXContent(new QueryParseContext(parser));