Elasti c NEST Client: обновление данных - PullRequest
0 голосов
/ 07 апреля 2020

Мне нужно обновить существующие данные. Есть ли лучший способ, чем восстановить старые данные -> изменить старые данные -> удалить старый индекс -> создать новый индекс -> массовая вставка новых данных Это кажется глупым. Более того, в итоге я получаю ок. В 2 раза выше store.size за index. Я не могу понять, почему это может быть.

Непосредственное групповое вставление измененных данных не работает: docs.count удваивается.

Есть идеи?

Обновление

Это моя основная вставка:

 var dataPointsBulkIndexOperationsPerBatchId = data.Select(
                item => new BulkIndexOperation<T>(item)
                            {
                                Index = indexName
                            });

            var allBulksRequest = new BulkRequest
                                      {
                                          Operations = new BulkOperationsCollection<IBulkOperation>(dataPointsBulkIndexOperationsPerBatchId),
                                          Refresh = Refresh.True
                                      };

            if (allBulksRequest.Operations.Any())
            {
                var bulkResponse = elasticClient.Bulk(allBulksRequest);
                bulkResponse.AssertResponseIsValidAndSuccessful();
            }

1 Ответ

0 голосов
/ 09 апреля 2020

Для обновления многих документов в одном запросе у вас есть два основных варианта:

1. Массовый API с операциями обновления

Использование массового API и отправка пакета операций обновления . Каждая операция обновления предоставляет те же параметры, что и для API обновления, поэтому можно выполнять частичные обновления, обновления по сценарию и т. Д. c.

Пример обновления по сценарию

var client = new ElasticClient();

var updates = new[] {
    new { Id = 1, Counter = 3 },
    new { Id = 2, Counter = 6 },
    new { Id = 3, Counter = 5 },
    new { Id = 4, Counter = 4 },
};

var bulkResponse = client.Bulk(b => b
    .Index("my_index")
    .UpdateMany(updates, (descriptor, update) => descriptor
        .Id(update.Id)
        .Script(s => s
            .Source("ctx._source.counter += params.counter")
            .Params(p => p
                .Add("counter", update.Counter)
            )
        )
    )
);

который отправляет следующий запрос

POST http://localhost:9200/my_index/_bulk
{"update":{"_id":1}}
{"script":{"source":"ctx._source.counter += params.counter","params":{"counter":3}}}
{"update":{"_id":2}}
{"script":{"source":"ctx._source.counter += params.counter","params":{"counter":6}}}
{"update":{"_id":3}}
{"script":{"source":"ctx._source.counter += params.counter","params":{"counter":5}}}
{"update":{"_id":4}}
{"script":{"source":"ctx._source.counter += params.counter","params":{"counter":4}}}

При обновлении по сценарию у вас есть доступ к документу _source в сценарии через ctx._source, поэтому в этом примере поле counter исходного документа увеличивается на значение параметра counter в операции обновления. Язык сценариев по умолчанию называется Painless , и сценарий может быть настолько сложным, насколько это необходимо. Рекомендуется параметризовать встроенный сценарий, как указано выше, чтобы Elasticsearch мог кэшировать и повторно использовать модуль компиляции, полученный в результате компиляции сценария.

При массовых обновлениях необходимо знать идентификаторы документов, которые Вам нужно sh обновить, чтобы сформировать операции массового обновления.

2. Обновление по запросу API

Обновление по запросу API позволяет выполнять обновления по сценарию для набора документов, соответствующих запросу.

Обновление по сценарию выполняет один и тот же сценарий для каждого соответствующего документа. Важнейшее различие между обновлением по запросу и массовым обновлением при выполнении обновления по сценарию заключается в том, что обновление по запросу не может быть параметризовано с разными значениями аргументов для обновления документа; все обновления выполняют одно и то же обновление по сценарию.

Пример обновления по запросу

var updateByQueryResponse = client.UpdateByQuery<object>(b => b
    .Index("my_index")
    .Query(q => q
        .Ids(ids => ids
            .Values(1,2,3,4)
        )
    )
    .Script(s => s
        .Source("ctx._source.counter += params.counter")
        .Params(p => p
            .Add("counter", 1)
        )
    )
);

, который отправляет следующий запрос

POST http://localhost:9200/my_index/_update_by_query?pretty=true 
{
  "query": {
    "ids": {
      "values": [1, 2, 3, 4]
    }
  },
  "script": {
    "source": "ctx._source.counter += params.counter",
    "params": {
      "counter": 1
    }
  }
}

Как и в случае массовых обновлений по сценарию, вы иметь доступ к документу _source в скрипте через ctx._source.

При обновлении по запросу вам не нужно знать идентификаторы документов, которые вы будете обновлять sh; для документов, на которые будет производиться обновление, будет выбран соответствующий запрос, который может быть match_all запросом на обновление всех документов.

...