ElasticSearch: удалить поле из всех документов, где оно существует (с помощью Painless?) - PullRequest
0 голосов
/ 18 июня 2019

Ситуация : у меня есть индекс со строгим отображением, и я хочу удалить из него старое поле, которое больше не используется. Поэтому я создаю новый индекс с отображением, которое не включает это поле, и я пытаюсь переиндексировать данные в новый индекс.

Проблема : Когда я переиндексирую, я получаю сообщение об ошибке, потому что я пытаюсь проиндексировать данные в поле, которое недоступно в отображении. Чтобы решить эту проблему, я хочу сначала удалить это поле из всех документов исходного индекса, прежде чем я смогу переиндексировать.

PUT old_index/_doc/1
{
    "field_to_delete" : 5
}
PUT old_index/_doc/2
{
    "field_to_delete" : null
}
POST _reindex
{
  "source": {
    "index": "old_index"
  },
  "dest": {
    "index": "new_index"
  }
}
"reason": "mapping set to strict, dynamic introduction of [field_to_delete] within [new_index] is not allowed"

1. Некоторые места, которые я нашел, предлагают сделать:

POST old_index/_doc/_update_by_query
{
  "script": "ctx._source.remove('field_to_delete')",
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "field_to_delete"
          }
        }
      ]
    }
  }
}

Однако это не соответствует документам, которые имеют явное значение null, поэтому повторное индексирование по-прежнему не выполняется после этого обновления.

2. Другие (например, члены команды Elastic на их официальном форуме) предлагают сделать что-то вроде:

POST old_index/_doc/_update_by_query
{
  "script": {
    "source": """
          if (ctx._source.field_to_delete != null) {
            ctx._source.remove("field_to_delete");
          } else {
            ctx.op="noop";
          }
      """
    }
  },
  "query": {
    "match_all": {}
  }
}

Однако это та же проблема - он не удаляет второй документ с явным значением null.

3. В конце концов я мог просто сделать:

POST old_index/_doc/_update_by_query
{
  "script": {
    "source": "ctx._source.remove("field_to_delete");"}
  },
  "query": {
    "match_all": {}
  }
}

Но это обновит все документы и для большого индекса может означать дополнительное время простоя во время развертывания.

1 Ответ

0 голосов
/ 18 июня 2019

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

POST old_index/_doc/_update_by_query
{
  "script": {
    "source": """
        if (ctx._source.containsKey("field_to_delete")) {
            ctx._source.remove("field_to_delete");
        } else {
          ctx.op="noop";
        }
      """
    }
  },
  "query": {
    "match_all": {}
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...