Как объединить объект вместо того, чтобы полностью заменить его с помощью API обновления (безболезненно) при записи ElasticSearch

Сценарий: есть документ A в ElasticSearch, и я хочу объединить в этот документ некоторые поля, существующие в документе B.

Документ А:

{ 
    "id": 121423,
    "name": "Sample Name",
    "timestamp": "2020-10-01T00:12:00",
    "age": 24
}

Документ B:

{
    "city": "New York",
    "job": "programmer"
}

Чтобы написать в этом документе, я могу использовать путь записи ES и подобное тело:

{"update":{"_index":"test-index","_id":"121423"}}
{"script": {"source":"if( ctx._source.containsKey('id') ){   ctx._source = params.param1; }","lang":"painless","params":{"param1":{"city": "New York", "job": "programmer"}}},"upsert":{"id":121423,"name": "Sample Name","timestamp": "2020-10-01T00:12:00","age": 24}}

Но, если документ A существует на ES, например, check do (if( ctx._source.containsKey('id') )) документ полностью перезаписывается. Я могу заменить приписанные параметры, чтобы выбрать каждый элемент поэтапно, например:

{   ctx._source.city = params.param1.city; ctx._source.job = params.param1.job }

Это решит мою проблему, НО из-за этого у меня возникнет проблема, логика не может быть статичной, потому что в реальном мире документ имеет много (очень много) полей, и поддержка приложения будет сложной. Желаемый документ в последнем обновлении должен быть примерно таким:

{ 
    "id": 121423,
    "name": "Sample Name",
    "timestamp": "2020-10-01T00:12:00",
    "age": 24,
    "city": "New York",
    "job": "programmer"
}

Итак, вопрос в том, как я могу обновить документ, добавляя новые поля небольшими шагами или используя только один оператор?

1 ответ

Вам, вероятно, следует просто добавить "doc_as_upsert": true Я никогда не пробовал это со сценарием, но он должен работать.

{ "update" : {"_id" : "2", "_index" : "index1", "retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"}, "doc_as_upsert" : true }