Удалить поле из документа 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.
- Получить первую версию вашего документа
- удалить поле
- нажмите эту новую версию вашего документа
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)