Jayaram
Jayaram

Reputation: 6606

Updating a nested object in elasticsearch

I have the below mapping for an index

{
  "mappings": {
    "xxxxx": {
      "properties": {
        "ID": {
          "type": "text"
        },
        "pairs": {
          "type": "nested"
        },
        "xxxxx": {
          "type": "text"
        }
      }
    }
  }
}

the pairs field is an array of objects with the below structure

{
    "id": "",
    "Answer": "",
    "Question": []
}

What i'm trying to do is retrieve a particular nested object and update it. I've tried the updateByQuery method with both partial doc/ script but i'm unable to update

script

var theScript = {
    "inline": "ctx._source.Answer = 'Elastic search update Test'"
}

client.updateByQuery({
    index: 'sample',
    _source: false,
    body: {
        query: {
            bool: {
                must: [
                    {
                        "match": {
                            "ID": '2rXdCf5OM9g1ebPNFdZNqW'
                        }
                    },
                    {
                        "nested": {
                            "path": "pairs",
                            "query": {
                                "match": {
                                    "pairs.id": "c1vNGnnQLuk"
                                }
                            },
                            "inner_hits": {}
                        }
                    }
                ]
            }
        },
        "script": theScript
    }
},function(err, body){
    if(err){
        throw err;
    }
    console.log('body: ', body)
    console.log('data: ', body.hits.hits)
})

partial doc

client.updateByQuery({
    index: 'sample',
    _source: false,
    body: {
        query: {
            bool: {
                must: [
                    {
                        "match": {
                            "ID": '2rXdCf5OM9g1ebPNFdZNqW'
                        }
                    },
                    {
                        "nested": {
                            "path": "pairs",
                            "query": {
                                "match": {
                                    "pairs.id": "c1vNGnnQLuk"
                                }
                            },
                            "inner_hits": {}
                        }
                    }
                ]
            }
        },
       "doc": {
        "Answer": 'Elastic search update Test'
       }
    }
},function(err, body){
    if(err){
        throw err;
    }
    console.log('body: ', body)
    console.log('data: ', body.hits.hits)
})

I'm getting the below error:

partial update

Error: [parsing_exception] Unknown key for a START_OBJECT in [doc]., with { line=1 & col=191 }

script

Error: [illegal_argument_exception] [sample][conversation][AWa-p9zBTJHq-_gvo-Af] didn't store _source

NOTE I would ideally like to use a partial doc update for this because the nested object is a bit complex and it wouldnt be possible to write an inline script

Elasticsearch version - 5.6

UPDATE

doing something like this works

{
    "script" : {
        "inline": "ctx._source.pairs= params.pairs",
        "lang": "painless",
        "params" : {
            "pairs" : [{...}, {...}, ...]
        }
    }
}

but this essentially means that everytime i update , i'm rewriting the entire pairs field (even though i only update one object in array) - this doesnt look ideal to me or is it fine?

Upvotes: 1

Views: 17884

Answers (3)

Abhishek Bairagi
Abhishek Bairagi

Reputation: 1

here's something which might help. Attaching a sample query

{
  "script": {
    "source": "ctx._source.nested_field.forEach(item -> item.nested_field2 = params.new_value)",
    "lang": "painless",
    "params": {
      "new_value": 100
    }
  },
  "query": {
    "match_all": {}
  }
}

my mapping was this

"mappings": {
        "properties": {
            "field1": {
                "type": "text"
            },
            "field2": {
                "type": "integer"
            },
            "nested_field": {
                "type": "nested",
                "properties": {
                    "nested_field1": {
                        "type": "text"
                    },
                    "nested_field2": {
                        "type": "integer"
                    },
                     "nested_field3": {
                        "type": "text"
                    }
                }
            }
        }
    }

Hope it helps :)

Upvotes: 0

Edgar Chavolla
Edgar Chavolla

Reputation: 836

There is a page with a quick tutorial about nested type management: How to manage nested objects in Elasticsearch documents . It explains how to add, remove and edit nested objects.

Upvotes: 9

Demi
Demi

Reputation: 51

There is no syntax for updating a particular nested document. You can only specify a nested field value, and it updates all nested documents. ES reindexes documents anyway with a partial update.

You can use parent-child documents to achieve that at some cost. If your have so many nested records then it may better fit your case.

Upvotes: 1

Related Questions