5

I am using update by query plugin (https://github.com/yakaz/elasticsearch-action-updatebyquery/) to update documents by query. In my case, there is nested field in document, the mapping is something like this:

"mappings": {
  "mytype": {
    "properties": {
      "Myfield1": {
        "type": "nested",
        "properties": {
          "field1": {
            "type": "string"
          },
          "field2": {
            "type": "long"
          }
        }
      },
      "Title": {
        "type": "string"
      }
    }
  }
}

Then I want to update the nested field Myfield1 by query with following request:

But unfortunately, it does not work.

{
  "query": {
    "match": {
      "Title": "elasticsearch"
    }
  },
  "script": "ctx._source.Myfield1 = [{'nestfield1':'foo blabla...','nestfield2':100},{'nestfield1':'abc...','nestfield2':200}]"
}

Does update by query support nested object?

BTW: any other ways to update document by query?

Is the update by query plugin the only choice?

Neo-coder
  • 7,715
  • 4
  • 33
  • 52
Youxu
  • 1,050
  • 1
  • 9
  • 34
  • hm, i was pretty sure, that you could update document without any plugins, just by indexing doc with same id - it will be replaced – Mysterion Apr 30 '15 at 08:13
  • 1
    Yes, I can partial update doc by id. But then I need firstly know the exact id of each doc which to be updated. So I prefer to "update by query" so that I can update the doc by query on any field. – Youxu Apr 30 '15 at 10:02
  • Perhaps this answer can help. https://stackoverflow.com/a/53192844/3838328 – Kamal Kunjapur Nov 16 '18 at 12:04

3 Answers3

10

This example uses _update_by_query

POST indexname/type/_update_by_query
{
  "query": {
    "match": {
      "Title": "elasticsearch"
    }
  },
  "script": {
    "source": "ctx._source.Myfield1= params.mifieldAsParam",
    "params": {
      "mifieldAsParam": [
        {
          "nestfield1": "foo blabla...",
          "nestfield2": 100
        },
        {
          "nestfield1": "abc...",
          "nestfield2": 200
        }
      ]
    },
    "lang": "painless"
  }
}
AFO
  • 101
  • 1
  • 3
6

Nested elements need to be iterated in painless script to update values

POST /index/_update_by_query
{
  "script": {
    "source": "for(int i=0;i<=ctx._source['Myfield1'].size()-1;i++){ctx._source.Myfield1[i].field1='foo blabla...';ctx._source.Myfield1[i].field2=100}",
    "lang": "painless"
  },
  "query": {
     "match": {
        "Title": "elasticsearch"
     }
  }
}

Nested elements value update if index is known

POST /index/_update_by_query
{
  "script": {
    "source": "ctx._source.Myfield1[0].field1='foo blabla...';ctx._source.Myfield1[0].field2=100;ctx._source.Myfield1[1].field1='abc...';ctx._source.Myfield1[1].field2=200;",
    "lang": "painless"
  },
  "query": {
    "match": {
         "Title": "elasticsearch"
    }
  }
}
karthi.613
  • 61
  • 1
  • 3
1

You can try with params, something like this:

"query" : {
    "match_all" : {}
},
"script" : "ctx._source.Myfield1 = Myfield1;",
"params": {
  "Myfield1": {
    "nestfield1": "foo blabla..."
  }
}

In my case I'm moving the data from not nested fields in nested fields. I need to add fake information to initialize the nested field. It looks like that:

"query" : {
    "match_all" : {}
},
"script" : "ctx._source.Myfield1 = Myfield1; ctx._source.Myfield1.nestfield1 = ctx._source.Myfield1Nestfield1;  ctx._source.Myfield1.nestfield2 = ctx._source.Myfield1Nestfield2;",
"params": {
  "Myfield1": {
    "nestfield1": "init_data"
  }
}
Tanya
  • 277
  • 3
  • 4