简体   繁体   中英

Elasticsearch update nested field with painless script in ElasticSearch API vs java API

Could someone explain what's wrong with ES java api? I'm making query to update by script with ES api and it works perfectly (below)

POST user/ut/520411_5752/_update
{
  "script": {
    "source": "ctx._source.cars.add(params.car)",
    "params": {
      "car": {
        "pub_id":155,
        "name":"qwerty"
      }
    }
  }
}

and java

HashMap<String, Object> params = new HashMap<>();
params.put("car", GSON.toJson(car));

Script inline = new Script(ScriptType.INLINE, "painless",
"ctx._source.cars.add(params.car)", 
params);
    
UpdateRequest request = new UpdateRequest(USER, UT, id).script(inline).retryOnConflict(1);
UpdateResponse update = elasticClient.update(request, RequestOptions.DEFAULT);

As you may guess java is failing with exception

ElasticsearchStatusException[Elasticsearch exception [type=mapper_parsing_exception, reason=object mapping for [cars] tried to parse field [null] as object, but found a concrete value]]

Tried different options, with empty car field, with filled car field, everytime getting an exception above.

Your java code LGTM and the problem comes from a "stale" version of your mapping that wouldn't be compatible with what your script would end up adjusting. Check my other answer from a while ago to gain more insight into this cryptic-sounding error.

Simply put, make sure your mapping looks something like this:

{
  "mappings": {
    "properties": {
      "cars": {
        "type": "object",
        "properties": {
          "pub_id": {
            "type": "integer"
          },
          "name": {
            "type": "text"
          }
        }
      }
    }
  }
}

that is, cars as an object and its contents clearly defined too. After that your script should work just fine.

BTW just to be perfectly safe, I'd add two more checks before I called .add :

if (ctx._source.cars != null && ctx._source.cars instanceof ArrayList) { ctx._source.cars.add(params.car) }

Seems like i surrender with RestHighLevelClient. But i remember that i have LowLevelClient and rewrite my update using it and it's working fine. Since i don't need to check the response, i don't need to parse it too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM