Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

elastic search, is it possible to update nested objects without updating the entire document?

I'm indexing a set of documents (imagine them as forum posts) with a nested object which is the user related to that post. My problem is that the user fields might be updated, but since the posts do not change they are not reindexed and the user nested objects become outdated. Is there a way to update the nested objects without reindexing the whole document again? Or the only solution would be to reindex all the related posts of a user everytime that the user changes?

like image 602
Marc M. Avatar asked Aug 21 '13 14:08

Marc M.


People also ask

Can we update data in elastic search?

The script can update, delete, or skip modifying the document. The update API also supports passing a partial document, which is merged into the existing document. To fully replace an existing document, use the index API.

How does nested query work in Elasticsearch?

Nested queryedit. Wraps another query to search nested fields. The nested query searches nested field objects as if they were indexed as separate documents. If an object matches the search, the nested query returns the root parent document.

Does Elasticsearch overwrite?

In Elasticsearch, to replace a document you simply have to index a document with the same ID and it will be replaced automatically. If you would like to update a document you can either do a scripted update, a partial update or both.


1 Answers

You can use the Update API.

curl -XPOST localhost:9200/docs/posts/post/_update -d '{     "script" : "ctx._source.nested_user = updated_nested_user",     "params" : {         "updated_nested_user" : {"field": "updated"}     } }' 

See this SO answer for full detail.

Note that update scripts support conditional logic, as shown here. So you could tag forum posts when the user changes, then iterate over the posts to update only posts with changed users.

curl -XPOST 'localhost:9200/docs/posts/post/_update' -d '{     "script" : "ctx._source.tags.contains(tag) ? "ctx._source.nested_user = updated_nested_John" : ctx.op = "none"",     "params" : {         "tag": "updated_John_tag",         "updated_nested_John" : {"field": "updated"}     } }' 

UPDATED

Perhaps my ternary operator example was incomplete. This was not mentioned in the question, but assuming that users change their info in a separate part of the app, it would be nice to apply those changes to the forum posts in one script. Instead of using tags, try checking the user field directly for changes:

curl -XPOST 'localhost:9200/docs/posts/post/_update' -d '{     "script" : "ctx._source.nested_user.contains(user) ? "ctx._source.nested_user = updated_nested_John" : ctx.op = "none"",     "params" : {         "user": "John",         "updated_nested_John" : {"field": "updated"}     } }' 

As mentioned, though, this may be a slower operation than reindexing the full posts.

like image 100
Scott Rice Avatar answered Sep 23 '22 07:09

Scott Rice