Помните проблему, когда данные запроса ES внезапно становятся пустыми

распределенный

основная среда

  • Версия эластичного поиска: 6.3.1
  • Клиентская среда: kibana 6.3.4, модуль приложения Java8.
    Среди них кибана в основном используется для диагностики запросов данных и просмотра логов, а основным клиентом является Java 8. Вставка данных и запрос реализованы на Java.

Введение в дело

Используйте elasticsearch для хранения основной информации о заказе. Поле в документе в основном длинное или ключевое слово. Файл order.json для создания индекса выглядит следующим образом:

{
  "doc": {
    "properties": {
      "id": {
        "type": "keyword",
        "index": true
      },
      "status": {
        "type": "byte",
        "index": true
      },
      "createTime": {
        "type": "long",
        "index": true
      },
      "uid": {
        "type": "long",
        "index": true
      },
      "payment": {
        "type": "keyword",
        "index": true
      },
      "commentStatus": {
        "type": "byte",
        "index": true
      },
      "refundStatus": {
        "type": "byte",
        "index": true
      }
    }
  }
}

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

выявить проблему

  • Это поле используется в программе, использующей termQuery, следующим образом:
QueryBuilders.termQuery("payment", req.getFilter().getOrder().getPayment())

Используйте команду для диагностики и запроса данных в кибане, но результаты не возвращаются.Команда запроса выглядит следующим образом:

GET /order/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "payment": "Alipay"
        }}
      ]
    }
  }
}

  • Запросите информацию о сопоставлении, чтобы узнать, является ли это ключевым словом:

GET /order/_mapping/doc

Возвращается ответ (отображается только поле оплаты):

{
  "order": {
    "mappings": {
      "doc": {
        "properties": {
          "payment": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

проблема вызывает

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

Разница между текстом и ключевым словом

Ключевое слово не разделяет слова и не меняет регистр сохраняемого контента, оно сохраняется как есть и может быть проиндексировано по умолчанию. Текст разделяет содержимое на слова и хранит их все в нижнем регистре, в то же время добавляется поле text.keyword, которое относится к типу ключевого слова и не будет индексироваться после более чем 256 символов.

Поскольку поле платежа стало текстовым, исходная программа использует запрос термина, используя «Alipay», а текст сохраняет «alipay», поэтому данные не могут быть найдены.

попробуйте устранить неполадки

  • Изменить значение платежа на нижний регистр
GET /order/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "payment": "alipay"
        }}
      ]
    }
  }
}
  • Или измените термин запроса, чтобы соответствовать запросу
GET /order/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
            "match": {
              "payment": "alipay"
            }
        }
      ]
    }
  }
}

Запрос имеет вывод данных и, как и ожидалось, проверенный метод работает.

отслеживание проблем

Очевидно, тип поля платежа, определенный в order.json, является ключевым словом, как оно может стать текстовым?

Поскольку среда, в которой возникает эта проблема, является тестовой средой, существует операция дедупликации и удаления индексных данных, а затем их импорта (немного нестандартно, но только в тестовой среде, а производственная среда этого делать не будет). ), функция повторного импорта данных документа индекса, es При создании автоматического сопоставления индекса строковое содержимое поля платежа станет текстовым.

Решение:

1. Удалить индекс

DELETE /order

2. Перестроить индекс в соответствии с order.json

PUT /order
{
    "mappings": {
        "doc": {
            "properties": {
              "id": {
                "type": "keyword",
                "index": true
              },
              "status": {
                "type": "byte",
                "index": true
              },
              "createTime": {
                "type": "long",
                "index": true
              },
              "uid": {
                "type": "long",
                "index": true
              },
              "payment": {
                "type": "keyword",
                "index": true
              },
              "commentStatus": {
                "type": "byte",
                "index": true
              },
              "refundStatus": {
                "type": "byte",
                "index": true
              }
            }
        }
    }
}

3. Запустите программу для заполнения данных (также можно использовать массовое использование)

резюме

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

Сосредоточьтесь на Java с высоким параллелизмом и распределенной архитектуре, большем обмене техническими сухими товарами и опытом, пожалуйста, обратите внимание на общедоступный номер: Сообщество архитектуры JavaJava架构社区