Удалить поле из документа Elasticsearch

Мне нужно удалить поле во всех документах, индексированных к Elasticsearch . Как мне это сделать. Поможет ли мне любой из запросов на удаление?

8 ответов

Решение

То, что сказал @backtrack, верно, но есть очень удобный способ сделать это в Elasticsearch. Elasticsearch выделит внутреннюю сложность удаления. Вам нужно использовать API обновления для достижения этой цели -

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : "ctx._source.remove(\"name_of_field\")"
}'

Вы можете найти больше документации здесь.

Примечание. Начиная с Elastic Search 6, вы должны включить заголовок типа контента:

-H 'Content-Type: application/json'

Elasticsearch добавлен update_by_query в 2.3. Этот экспериментальный интерфейс позволяет выполнять обновление для всех документов, которые соответствуют запросу.

Внутренне эластичный поиск выполняет сканирование / прокрутку для сбора пакетов документов, а затем обновляет их, как интерфейс массового обновления. Это быстрее, чем делать это вручную с вашим собственным интерфейсом сканирования / прокрутки из-за отсутствия накладных расходов на сеть и сериализацию. Каждая запись должна быть загружена в оперативную память, изменена и затем записана.

Вчера я удалил большое поле из моего кластера ES. Я видел постоянную пропускную способность в 10000 записей в секунду во время update_by_query, ограниченную ЦП, а не IO.

Посмотри в настройку conflict=proceed если у кластера есть другой трафик обновления, или вся работа остановится, когда он достигнет ConflictError когда одна из записей обновляется под одной из партий.

Аналогичным образом wait_for_completion=false вызовет update_by_query через интерфейс задач. В противном случае работа будет прервана, если соединение закрыто.

URL:

http://localhost:9200/type/_update_by_query?wait_for_completion=false&conflict=proceed

POST body:

{
  "script": ctx._source.remove("name_of_field"),
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "name_of_field"
          }
        }
      ]
    }
  }
}

Начиная с Elasticsearch 1.43, встроенные скрипты Groovy по умолчанию отключены. Вам нужно будет включить его для встроенного скрипта, как этот, добавив script.inline: true в ваш конфигурационный файл.

Или загрузите Groovy в качестве сценария и используйте "script": { "file": "scriptname", "lang": "groovy"} формат.

Вы можете использовать _update_by_query

Пример 1:

index: my_index

поле: user.email

POST my_index/_update_by_query?conflicts=proceed
{
    "script" : "ctx._source.user.remove('email')",
    "query" : {
        "exists": { "field": "user.email" }
    }
}

Пример 2:

index: my_index

поле: total_items

POST my_index/_update_by_query?conflicts=proceed
{
    "script" : "ctx._source.remove('total_items')",
    "query" : {
        "exists": { "field": "total_items" }
    }
}

Предыдущие ответы не сработали для меня.

Мне пришлось добавить ключевое слово "inline":

POST /my_index/_update_by_query
{
  "script": {
    "inline": "ctx._source.remove(\"myfield\")"
  },
  "query" : {
      "exists": { "field": "myfield" }
  }
}

По умолчанию это невозможно, потому что сейчас Lucene не поддерживает это. По сути, вы можете помещать или удалять только целые документы Lucene из индексов Lucene.

  1. Получить первую версию вашего документа
  2. удалить поле
  3. нажмите эту новую версию вашего документа
      PUT /products/_update/1
{
  "docs" :{
    "price": 12,
    "quantity": 3,
    "in_stock": 6
  }
}

Now if I need to remove "quantity" then:

POST products/_update/1
{
  "script": {
    "source": "ctx._source.remove(\"quantity\")"
  }
}

Я хотел бы добавить к предыдущим ответам, что после удаления поля размер индекса не изменится . придется создать новый индекс или использовать _reindex api.

      curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
 "source": {
   "index": "old-index"
 },
 "dest": {
   "index": "new-index"
}}

'

Для тех, кто придерживается массового API, альтернативой удаления поля (ов) документа (ов) является предоставление дополнительного скрипта в updateполезная нагрузка действия массового вызова API.

Командная часть такая же, как описано в официальной документации:

curl -s -H "Content-Type: application/x-ndjson"  -H "Accept: application/json; indent=4;" \
     --data-binary   '@es_bulk_edit_data.json'  --request POST \
     "http://YOUR_ELASTICSEARCH_HOST:PORT_NUM/OPTIONAL_INDEX/OPTIONAL_TYPE/_bulk?pretty"

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

// assume you attempt to add one field `artist`, update one field `num_views`,
// and delete one field `useless` in the document with type t1 and ID 123
{"update": {"_type": "t1", "_id": "123"}}
{"doc": {"artist": "new_artist", "num_views": 67}}
{"update": {"_type": "t1", "_id": "123"}}
{"script": {"source": "ctx._source.remove(params.del_field_name)", "lang":"painless", "params":{"del_field_name": "useless"}}}

Заметка:

  • Массовый API, doc раздел нельзя разместить с script в той же полезной нагрузке, ElasticSearch, похоже, отказывается обрабатывать такую ​​структуру полезной нагрузки и возвращает ответ об ошибке 400 bad request и причина сообщения будет Validation Failed: 1: can't provide both script and doc;. Вот почему я разделяю удаление и все остальные операции на две полезные нагрузки.
  • они протестированы в версиях 5.6 и 6.6, также должны получить тот же результат в последней версии (v7.10)
Другие вопросы по тегам