如何使用Elasticsearch API的ScriptQueryBuilder

huangapple go评论63阅读模式
英文:

How to use Elasticsearch API ScriptQueryBuilder

问题

我使用Elasticsearch 6.8.12版本,我需要在Java中添加一个update by query的API,我查阅了ES文档并了解到ScriptQueryBuilder可以构建脚本,但我不知道如何使用它,我在Google上搜索了但没有找到任何有用的教程。

分享我目前了解的内容:

  1. 我们可以使用_update_by_query来更新,就像MySQL中的set extra=test where user='kimchy',参考es update by query
POST twitter/_update_by_query
{
  "script": {
    "source": "ctx._source['extra'] = 'test'",
    "lang": "painless"
  },
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
  1. ScriptQueryBuilder可以生成脚本查询的JSON,依赖:
<dependency>
      <groupId>org.elasticsearch</groupId>
      <artifactId>elasticsearch</artifactId>
      <version>6.8.12</version>
</dependency>

我尝试了下面的代码,但运行失败:

public String generateUpdateQuery() {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Map<String, Object> params = new HashMap<>(16);
        params.put("user","kimchy");
        Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, null, null, params);
        ScriptQueryBuilder scriptQueryBuilder = QueryBuilders.scriptQuery(script);
        System.out.println(scriptQueryBuilder.toString());
        return null;
}

我的需求:
我需要使用ScriptQueryBuilderQueryBuilders来生成脚本JSON,ES API为_update_by query

谢谢!

英文:

I use Elasticsearch 6.8.12, i need to add a update by query API in Java, i check docs in ES and know ScriptQueryBuilder can build script but i don't know how to use it, i searched in google and couldn't found any usable tutorial.

Share what i know currently:

  1. we can use _update_by_query to update like Mysql set extra= test where user=&#39;kimchy&#39;, refer to
    es update by query
POST twitter/_update_by_query
{
  &quot;script&quot;: {
    &quot;source&quot;: &quot;ctx._source.[&#39;extra&#39;] = &#39;test&#39;&quot;,
    &quot;lang&quot;: &quot;painless&quot;
  },
  &quot;query&quot;: {
    &quot;term&quot;: {
      &quot;user&quot;: &quot;kimchy&quot;
    }
  }
}
  1. ScriptQueryBuilder can generate script query json,
    dependency:
&lt;dependency&gt;
      &lt;groupId&gt;org.elasticsearch&lt;/groupId&gt;
      &lt;artifactId&gt;elasticsearch&lt;/artifactId&gt;
      &lt;version&gt;6.8.12&lt;/version&gt;
&lt;/dependency&gt;

I tried below code but it run failed:

public String generateUpdateQuery() {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Map&lt;String, Object&gt; params = new HashMap&lt;&gt;(16);
        params.put(&quot;user&quot;,&quot;kimchy&quot;);
        Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, null, null, params);
        ScriptQueryBuilder scriptQueryBuilder = QueryBuilders.scriptQuery(script);
        System.out.println(scriptQueryBuilder.toString());
        return null;
}

My requirement:
I need to generate script json using ScriptQueryBuilder QueryBuilders, the ES API is _update_by query

Thanks!

答案1

得分: 0

解决方案:

对于 SQL 查询部分:

{
    "query": {
        "term": {
            "user": "kimchy"
        }
    },
    "script": {
        "source": "ctx._source.extra = \"test\";",
        "lang": "painless"
    }
}

使用 ScriptQueryBuilder 的代码部分:

public String generateUpdateByQuery() {

    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.filter(QueryBuilders.termQuery("user", "kimchy"));
    StringBuilder sb = new StringBuilder();

    sb.append(String.format("ctx._source.%s = %s;", "extra", String.format("\"%s\"", "test")));

    // 如果没有参数,保持为空,在 Script 中需要
    Map<String, Object> params = new HashMap<>(16);
    Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, "painless", sb.toString(), params);
    ScriptQueryBuilder scriptQueryBuilder = QueryBuilders.scriptQuery(script);
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(boolQueryBuilder);

    // 处理 SQL 部分
    JSONObject scriptOuter = JSON.parseObject(scriptQueryBuilder.toString());
    JSONObject scriptJson = (JSONObject)scriptOuter.get("script");
    JSONObject queryJson = JSON.parseObject(searchSourceBuilder.toString());
    scriptJson.putAll(queryJson);
    scriptJson.remove("boost");
    
    // 查询:
    return scriptJson.toJSONString();
}

如果你的查询包含参数,像这样:

"script": {
    "source": "ctx._source.extra = params.extraVal;",
    "lang": "painless",
    "params": {
        "extraVal": "test"
    }
}

那么在上面的参数映射 params 中设置参数:

Map<String, Object> params = new HashMap<>(16);
params.put("extraVal", "test");
Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, "painless", sb.toString(), params);
英文:

Solution:

For sql:

{
    &quot;query&quot;: {
    &quot;term&quot;: {
      &quot;user&quot;: &quot;kimchy&quot;
    }
  },
    &quot;script&quot;: {
        &quot;source&quot;: &quot;ctx._source.extra = \&quot;test\&quot;;&quot;,
        &quot;lang&quot;: &quot;painless&quot;
    }
}

Code using ScriptQueryBuilder:

public String generateUpdateByQuery() {

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.filter(QueryBuilders.termQuery(&quot;user&quot;, &quot;kimchy&quot;));
StringBuilder sb = new StringBuilder();

sb.append(String.format(&quot;ctx._source.%s = %s;&quot;, &quot;extra&quot;, String.format(&quot;\&quot;%s\&quot;&quot;,&quot;test&quot;)));


// if no params, keep it empty, it required in Script
Map&lt;String, Object&gt; params = new HashMap&lt;&gt;(16);
Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, &quot;painless&quot;, sb.toString(), params);
ScriptQueryBuilder scriptQueryBuilder = QueryBuilders.scriptQuery(script);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(boolQueryBuilder);

// deal sql
JSONObject scriptOuter = JSON.parseObject(scriptQueryBuilder.toString());
JSONObject scriptJson = (JSONObject)scriptOuter.get(&quot;script&quot;);
JSONObject queryJson = JSON.parseObject(searchSourceBuilder.toString());
scriptJson.putAll(queryJson);
scriptJson.remove(&quot;boost&quot;);
// query:
return scriptJson.toJSONString()
}

If your query contains params like that:

 &quot;script&quot;: {
        &quot;source&quot;: &quot;ctx._source.extra = params.extraVal;&quot;,
        &quot;lang&quot;: &quot;painless&quot;
        &quot;params&quot;: {
            &quot;extraVal&quot;:&quot;test&quot;
        }
    }

Then set params in the above map params

Map&lt;String, Object&gt; params = new HashMap&lt;&gt;(16);
params.put(&quot;extraVal&quot;,&quot;test&quot;)
Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, &quot;painless&quot;, sb.toString(), params);

huangapple
  • 本文由 发表于 2020年9月27日 23:02:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/64089886.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定