返回elasticsearch java api中已分析的非存储文本字段的子字符串

问题描述 投票:1回答:2

我的项目有一个字符串字段(名称是urlOrContent),它可以很小(小于50个字符)或很长(超过50个字符),我只想每次返回前50个字符在特定的查询。我的数据库是弹性搜索,我的问题在this link中提出,提问者的回答似乎是正确的(urlOrContent字段被分析和非存储文本字段)。它使用以下脚本:

{
   "script_fields": {
      "substring": {
         "script": {
            "lang": "painless",
            "inline": "params._source.text.substring(0, 100)"
         }
      }
   }
}

但我的主要问题是我找不到相应的elasticsearch java api代码。实际上,应该在下面的代码中添加什么,它只返回urlOrContent字段的前50个字符?请注意,在某些情况下,此字段可能甚至不包含50个字符,然后应返回整个字符串。

String queryString =
    EnumLinkFields.CREATE_TIME.getFieldName() + ":(>=" + dateFrom + " AND <=" + dateTo + ")";

QueryBuilder query = QueryBuilders.queryStringQuery(queryString);

SearchResponse response = TRANSPORT_CLIENT.prepareSearch(MY_INDEX)
                .setTypes(MY_TYPE)
                .setSearchType(SEARCH_TYPE)
                .setQuery(query)
                .setFetchSource(null, new String[]{EnumLinkFields.USER_ID.getFieldName()})
                .setFrom(offset)
                .setSize(count)
                .addSort(orderByField, sortOrder)
                .execute().actionGet();
java elasticsearch
2个回答
0
投票

我找到了最好的答案。

String queryString =
    EnumLinkFields.CREATE_TIME.getFieldName() + ":(>=" + dateFrom + " AND <=" + dateTo + ")";

QueryBuilder query = QueryBuilders.queryStringQuery(queryString);

String codeUrlOrContent = "if (" + EnumElasticScriptField.URL_OR_CONTENT.getFieldName() + ".length() > 50) {" +
        "return " + EnumElasticScriptField.URL_OR_CONTENT.getFieldName() + ".substring(0, 50);" +
        "} else { " +
        "return " + EnumElasticScriptField.URL_OR_CONTENT.getFieldName() + "; }";

Script scriptUrlOrContent = new Script(ScriptType.INLINE, "painless",
        codeUrlOrContent, Collections.emptyMap());

Script scriptIsUrl = new Script(ScriptType.INLINE, "painless",
        EnumElasticScriptField.IS_URL.getFieldName(), Collections.emptyMap());

SearchResponse response = TRANSPORT_CLIENT.prepareSearch(MY_INDEX)
                .setTypes(MY_TYPE)
                .setSearchType(SEARCH_TYPE)
                .setQuery(query)
                .addScriptField(EnumLinkFields.URL_OR_CONTENT.getFieldName(), 
                     scriptUrlOrContent)
                .addScriptField(EnumLinkFields.IS_URL.getFieldName(), scriptIsUrl)
                .setFrom(offset)
                .setSize(count)
                .addSort(orderByField, sortOrder)
                .execute().actionGet();

请注意,必须删除对setFetchSource函数的调用,并且必须通过脚本返回所有返回的字段。


0
投票

您可以将script_fields查询放在查询对象中,即在setQuery(查询)中。您的查询对象现在应该看起来像这样。

    "query" : {
        "term" : { "user" : "kimchy" }
    }

在对象中添加script_fields后,它应该变为:

"query" : {
  "term" : { "user" : "kimchy" }
},
"script_fields": {
  "urlOrContent": {
     "script": {
        "lang": "painless",
        "inline": "if(params._source.urlOrContent.length() > 50){
                    params._source.urlOrContent.substring(0, 50)
                   }
                   else {
                   params._source.urlOrContent
                   }"  
   }
  }
}

生成的匹配将包含一个包含所需子字符串的字段数组。

您必须通过更改elasticsearch.yml文件来启用脚本,然后重新启动elasticsearch:script.engine.painless.inline.aggs:on

script.engine.painless.inline.update:on

script.inline:on

script.indexed:on

© www.soinside.com 2019 - 2024. All rights reserved.