ElasticSearch 中的 SearchHits 不包含使用 Java API 的字段

Mic*_*dis 4 java elasticsearch

我正在运行此代码以返回匹配项

    public ArrayList<InnerText> suggest(String text, boolean isPersonal){

            TransportClient transportClient = new TransportClient();
            Client ESclient = transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", 9300));
            OrientGraph graph = new OrientGraph(ConnectionStrings.dbConnection);
            Map<String, Object> template_params = new HashMap<>();
            template_params.put("innerText", text);
            SearchResponse response = ESclient.prepareSearch()
                    .setTemplateName("innerText_match")
                    .setTemplateType(ScriptService.ScriptType.FILE)
                    .setTemplateParams(template_params)
                    .execute()
                    .actionGet();
            int index = 0;
            ArrayList<InnerText> list = new ArrayList<InnerText>();
            for (SearchHit hit : response.getHits()) {

                //String uuid = hit.field(InnerTextProps.uuid).toString();
                //InnerText innerText = vertexToInnerText(graph.getVertexByKey("InnerText.uuid",uuid),false);
                //list.add(null);
                //hit fields map is  org.elasticsearch.util.collect.EmptyImmutableMap
            }
            return list; 
    }
Run Code Online (Sandbox Code Playgroud)

我得到了回复,但每个 SearchHits 的字段映射是空的 (org.elasticsearch.util.collect.EmptyImmutableMap).Hits 有正确的 id 和类型。使用 Sense 插件时,我看到使用相同的查询正确存储和检索内容。我究竟做错了什么?

谢谢!

mvr*_*ijn 5

经过对不同方法的一些探索,我发现:

  • SearchHit.sourceAsMap() 如果没有请求特定字段,将允许您访问数据
  • SearchHit.getFields() 将允许您访问查询中请求的特定字段 SearchResponse.addFieldDataField( String )

当请求整个源时(默认情况下),Map对象将包含String值或后续Map值:

Map<String,Object> contents = hit.sourceAsMap();
for ( String name : contents.keySet() )
{
    Object value = contents.get(name);
    System.out.println( "Hit field: "+name+ " object: "+value.getClass().getName() );
    if ( contents.get(name) instanceof java.util.HashMap )
    {
        // Handle map object
    }
    else
    {
        // Handle string value
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,当您请求特定字段时,您可以使用更简单的 IMHOSearchHitSearchHitFieldAPI处理那些字段。

编辑

经过更多的探索,从SearchHitField对象中检索值毕竟不是那么容易:

        Map<String,SearchHitField> fields = hit.getFields();
        System.out.println( "Hit fields: "+fields.size() );
        for ( SearchHitField field : fields.values() )
        {
            System.out.println( " Hit field: "+field.getName() );
            System.out.println( " Value: "+field.getValue() );
        }
Run Code Online (Sandbox Code Playgroud)

仅对null我的情况下的值产生收益。未完待续...

EDIT2:最终解决方案

首先,该addFieldDataField()方法仅在您指定要检索的原始字段时才有效。使用分析的字段将导致错误“字段数据加载被禁止<fieldname>

其次,当您使用 检索字段时addField(),请始终指定字段,否则查询将失败。

  • SearchResponse.addFieldDataField( <fieldname>.raw )
  • SearchResponse.addField( <leaffieldname> )

现在您可以使用 检索该字段的内容SearchHitField.getValue()。祝你好运。