1

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?

1
  • Not an answer, but I've found elasticsearch to handle nested objects poorly -- especially lists and especially when combined with the rest of the ecosystem like Kibana. Everything works more smoothly when you have more smaller flatter documents to convey the same information. Commented Oct 29, 2018 at 15:05

3 Answers 3

10

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.

Sign up to request clarification or add additional context in comments.

1 Comment

An addition I'd make to this: If the script didn't update anything (because the nested object to be updated couldn't be found, for example), then setting ctx.op = \"none\" works wonderfully at making the result not be updated:
1

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.

Comments

0

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 :)

Comments

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.