Search code examples
elasticsearchelasticsearch-painless

How to deep clone a Object field in painless script


I want to cerate a new field to store the old value when updating a object field.

The original doc is:

 {
        "_index" : "test",
        "_id" : "15895_-1",
        "_source" : {
            "device" : {
                  "standard": {
                       "name" : "unknown",
                       "brand" : "unknown"
                  },
                  "other": "other"
             }
        }
}

This is my updateByquery code:

GET test/_update_by_query
{
  "script": {
    "source": """
    if (params.deviceStandard != null) {
      ctx._source['device_algoed'] = ctx._source['device'];
      
      ctx._source['device']['standard']['series'] = params.deviceStandard.series;
      ctx._source['device']['standard']['brand'] = params.deviceStandard.brand;
    }
    """,
    "params": {
      "deviceStandard": {
        "series" : "unknown",
        "brand" : "OPPO"
      }
    }
  },
  "query": {
    "bool": {
      "filter": {
        "term": {
          "_id": "15895_-1"
        }
      }
    }
  }
}

When I change the ctx._source['device']['standard'], the ctx._source['device_algoed'] will change too. So how to deep clone the ctx._source['device']['standard'] to ctx._source['device_algoed']?


Solution

  • What you can do is to create a new map out of the origin one:

      ctx._source['device_algoed'] = [:];
      ctx._source['device_algoed'].putAll(ctx._source['device']);
    

    And then you can freely modify ctx._source['device'] without impacting ctx._source['device_algoed']

    That's it!