I don't know the "best" solution. It depends.
My experience in the past was that I was never updating a sub internal object in my application but the root object with may be only modifications in the inner object.
If you think of a SQL model, behind the scene the update was made only in the inner object but from a user or functional point of view, the change was made globally.
In which case, I was sending again the whole global object to Elasticsearch.
In update scenario, we have to handle like, if a document came with an update, we have to store only those fields, fields which are not present in document should be removed from ES document without disturbing 4th object.
That is making the job you have to do on your end more complicated IMO.
What I'd probably do is to read the document from Elasticsearch (GET by ID), then merge it with whatever you want and send it back as a whole.
That's basically what the update API is doing behind the scene. But that way you can better control complex scenario where you have to rewrite a whole object.
But if you find a better way, that's great. Feel free to share your solution here.