Elasticsearch обновляет все поле _source на основе поискового запроса

"_source": {
         "id": "5b1676493d21784208c36041",
         "label": "name",
         "properties": {
           "name": "patrick"
         },
         "updatedAt": 1528259039542
       }

Я хочу обновить этот документ на основе id (а не _id) новым документом.

Что-то вроде этого:

    "_source": {
             "dataSource": "ELASTIC",
             "entity": "vertices",
             "label": "vertices",
             "id": "5b1676493d21784208c36041",
             "properties": {
                     "name": "patrick"
                  },
             "updatedAt": 1528259039542
           }

версия elasticsearch: 6.2, ES Java API: 6.2


person Abhijith S    schedule 07.06.2018    source источник
comment
Так как в поисковой системе нет такой вещи, как обновление, просто удалите старый документ, а затем добавьте новый. elastic.co/guide/en/ elasticsearch/reference/current/ может помочь.   -  person Harald    schedule 07.06.2018
comment
Да, @Харальд, я думал так же.   -  person Abhijith S    schedule 07.06.2018


Ответы (3)


Вы можете добиться того, чего хотите, используя обновить с помощью API запроса, примерно так:

POST index/_update_by_query
{
  "query": {
    "match": {
      "id": "5b1676493d21784208c36041"
    }
  },
  "script": {
    "source": "ctx._source = params",
    "params": {
       "dataSource": "ELASTIC",
       "entity": "vertices",
       "label": "vertices"
    }
  }
}

ОБНОВЛЕНИЕ: использование Java API

Map<String, String> params = new HashMap<>();
params.put("dataSource", "ELASTIC");
params.put("entity", "vertices");
params.put("label", "vertices");

UpdateByQueryRequestBuilder updateByQuery = UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source("index")
    .filter(QueryBuilders.matchQuery("id", "5b1676493d21784208c36041"))
    .size(1000)
    .script(new Script(ScriptType.INLINE, "painless", "ctx._source.putAll(params)", params));
BulkByScrollResponse response = updateByQuery.get();

Дополнительные сведения об использовании UpdateByQuery Java API и Java-клиент отдыха высокого уровня

person Val    schedule 07.06.2018
comment
Это имя языка сценариев, используемого в сценарии, указанном во втором параметре. - person Val; 07.06.2018
comment
Пожалуйста, обновите свой вопрос с результатами ... более разборчиво, чем здесь - person Val; 08.06.2018
comment
Можете ли вы предоставить значимую часть трассировки стека? - person Val; 08.06.2018
comment
Давайте продолжим это обсуждение в чате. - person Abhijith S; 08.06.2018
comment
"ctx._source = params" Это также не поддерживает - person Abhijith S; 08.06.2018
comment
Мне любопытно узнать, что делает ваш метод introspect()... Можете ли вы создать простой HashMap, как я сделал в моем примере, и попробовать его? Начните с простого, а затем повторяйте. - person Val; 08.06.2018
comment
когда я пытался использовать HashMap, как вы сказали, ctx._source = params не поддерживает - person Abhijith S; 08.06.2018
comment
Установка для ctx.op любого другого значения приводит к ошибке. Установка любого другого поля в ctx вызывает ошибку. из документации es: elastic.co/guide/en/elasticsearch/client/java-api/current/ - person Abhijith S; 10.06.2018
comment
Небольшое изменение @Val .script(new Script(ScriptType.INLINE, "painless", "ctx._source = params", params)); - person Abhijith S; 10.06.2018
comment
Вы правы, я инвертировал безболезненное и код. Я не думаю, что это причина для отрицательного голосования. Я обновил код. Теперь работает лучше? - person Val; 11.06.2018
comment
Нет, на самом деле мое требование отличается, это создание поля ctx в _source - person Abhijith S; 12.06.2018
comment
Что делает скрипт, так это заменяет все поля _source теми, которые присутствуют в params, как вы и просили. ctx._source — это способ доступа к исходному документу, и мы присваиваем ему значения параметров - person Val; 12.06.2018
comment
эй @Val, не могли бы вы проверить мой обновленный вопрос? Вот что такое мое требование. - person Abhijith S; 12.06.2018
comment
Вы должны были создать новый вопрос, так как теперь все комментарии не синхронизированы с вопросом и ответом :-( - person Val; 12.06.2018
comment
Почему мы не можем удалить комментарии, и вы можете отредактировать свой ответ, соответствующий моему обновленному вопросу, верно? - person Abhijith S; 12.06.2018
comment
Потому что я предпочитаю тратить время на помощь людям, а не курировать комментарии на основе отредактированных вопросов ;-) - person Val; 12.06.2018
comment
Красиво: П. Кстати, я пытался выполнить поиск с помощью идентификатора и обновления, но с двумя вызовами API (get и put). На самом деле моя интуиция говорит, что это можно решить с помощью одного запроса сценария ИЛИ в одном вызове API. - person Abhijith S; 12.06.2018
comment
Просто замените скрипт на этот ctx._source.putAll(params), он сохранит исходный код, но перезапишет его со всеми полями, присутствующими в параметрах. - person Val; 12.06.2018
comment
Становимся ближе @Val _source: {ctx: {_routing: null, _parent: null, _index: vertices, _type: vertices, _id: AeZz82MBrouOs8r6VAyE, _version: 1}, id: 5b1676493d21784208c36041, label: updatedLabel, properties: {name: sheji} , обновлено: 1528797832451 } . Но мне не нужно это ctxfield. Могу ли я удалить это? - person Abhijith S; 12.06.2018
comment
В любом случае обновите свой ответ @Val, я приму ответ. :) - person Abhijith S; 12.06.2018
comment
сначала разберусь почему - person Val; 12.06.2018
comment
В будущем, пожалуйста, не изменяйте вопрос таким образом, чтобы опубликованные ответы больше не имели смысла. - person Val; 13.06.2018
comment
Конечно, @Val, я обязательно приму это во внимание. - person Abhijith S; 13.06.2018

"ctx._source.putAll(params)" была хорошей попыткой, но, к сожалению, она перемещает все существующие поля под _source.ctx.

Итак, у меня работает следующее (ES 6.1):

"for (k in params.keySet()){if (!k.equals('ctx')){ctx._source.put(k, params.get(k))}}"
person jetnet    schedule 13.03.2019

Спасибо @jetnet за идею перебрать все записи на карте. Когда я использовал сценарий, он все еще заменял весь объект, поэтому мне пришлось адаптировать его, как показано ниже, чтобы сохранить поля, не предоставленные во время операции обновления. Для контекста, если я сначала вставлю документ, который имеет три объекта, каждый с 2 ​​полями, если я затем обновлю этот документ с теми же 3 объектами, но с 1 полем каждый, вывод будет таким, что я получаю документ с 3 объектами каждый с 1 полем вместо 3 объектов по 2 поля, как было у меня изначально.

Мне пришлось адаптировать скрипт @jetnet, чтобы получить желаемый результат: не перезаписывать свойства объекта.

POST /transaction_index/_update/33384637-3137-3132-5543-31304c4c3151
{
   "script": {
      "source": "if (ctx._source.Metadata == null || params.Metadata.Version >= ctx._source.Metadata.Version) { for (k in params.keySet()){ if (ctx._source[k] != null) { ctx._source[k].putAll(params.get(k)) } else { ctx._source.put(k, params.get(k)) } } } else { ctx.op = 'none' }",
      "params": {
         "Transaction": {
            "TransactionId": "33384637-3137-3132-5543-31304c4c3151",
            "TransactionKey": "Key1"
         },
         "Message": {
            "MessageId": "505a5953-374a-385a-4a48-52353549445a",
            "Context": "This is a test context"
         },
         "MessageDefinition": {
            "MessageDefinitionId": "a1c05e06-fa6b-40ce-992f-d083ff6c0243",
            "Code": 1010101010
         },
         "Metadata": {
            "Version": 1,
            "CreateTime": "2020-09-04T14:27:51.1986439+01:00",
            "IsLatest": true,
            "IsDummy": false,
            "VersionString": "20200903111111"
         }
    }
 },
 "scripted_upsert": true,
 "upsert": {}
}

    
person Kwex    schedule 04.09.2020