1

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='kimchy', refer to es update by query
POST twitter/_update_by_query
{
  "script": {
    "source": "ctx._source.['extra'] = 'test'",
    "lang": "painless"
  },
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
  1. ScriptQueryBuilder can generate script query json, dependency:
<dependency>
      <groupId>org.elasticsearch</groupId>
      <artifactId>elasticsearch</artifactId>
      <version>6.8.12</version>
</dependency>

I tried below code but it run failed:

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;
}

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

Thanks!

1 Answer 1

0

Solution:

For sql:

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

Code using 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")));


// if no params, keep it empty, it required in 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);

// deal 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");
// query:
return scriptJson.toJSONString()
}

If your query contains params like that:

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

Then set params in the above map params

Map<String, Object> params = new HashMap<>(16);
params.put("extraVal","test")
Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, "painless", sb.toString(), params);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks ! But we are still writing "ctx._source.%s = %s;" as a String value, does ScriptQueryBuilder have a DSL to build?
Hi @AlpcanYıldız, I used ES low level API to build dsl string, if you want to use it, you can use high level API to build dsl. You can joint dsl string or use XContentFactory.jsonBuilder() to build dsl. See https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-put-stored-script.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.