Получение согласованной оценки
Тот факт, что Elasticsearch работает с фрагментами и репликами, создаёт сложности при обеспечении хорошей оценки.
Оценки не воспроизводимы
Предположим, один и тот же пользователь дважды подряд выполняет один и тот же запрос, и документы возвращаются в разном порядке каждый раз — это довольно неудобный опыт, не так ли? К сожалению, это может произойти, если у вас есть реплики (index.number_of_replicas больше нуля). Причина в том, что Elasticsearch выбирает фрагменты, к которым должен обратиться запрос, по круговому циклу, поэтому весьма вероятно, что при выполнении одного и того же запроса дважды подряд он будет обращаться к разным копиям одного и того же фрагмента.
Почему это проблема? Статистика индекса — важная часть оценки. И эта статистика индекса может отличаться между копиями одного и того же фрагмента из-за удалённых документов. Как вы знаете, когда документы удаляются или обновляются, старый документ не удаляется из индекса сразу, он просто помечается как удалённый, и он будет удалён с диска только при следующей слиянии сегмента, к которому принадлежит этот старый документ. Однако по практическим причинам, эти удалённые документы учитываются для статистики индекса. Представьте себе, что первичный фрагмент только что завершил большое слияние, которое удалило множество удалённых документов, тогда у него может быть статистика индекса, которая существенно отличается от реплики (которая всё ещё содержит множество удалённых документов), так что оценки тоже будут отличаться.
Рекомендуемый способ решения этой проблемы — использовать строку, которая идентифицирует вошедшего пользователя (например, идентификатор пользователя или идентификатор сессии) в качестве параметра предпочтения. Это гарантирует, что все запросы данного пользователя всегда будут обращаться к тем же фрагментам, поэтому оценки остаются более согласованными между запросами.
Это решение имеет ещё одно преимущество: когда у двух документов одинаковая оценка, они будут сортироваться по их внутреннему идентификатору документа Lucene (который не связан с _id) по умолчанию. Однако эти идентификаторы документов могут отличаться между копиями одного и того же фрагмента. Поэтому, всегда обращаясь к одному и тому же фрагменту, мы получим более согласованную сортировку документов, имеющих одинаковые оценки.
Релевантность выглядит неправильно
Если вы заметили, что два документа с одинаковым содержимым получают разные оценки или что точное совпадение не занимает первое место в рейтинге, то проблема может быть связана с фрагментацией. По умолчанию Elasticsearch поручает каждому фрагменту вычисление собственных оценок. Однако, поскольку статистика индекса является важным фактором при расчёте оценок, это работает хорошо только в том случае, если фрагменты имеют сходную статистику индекса. Предполагается, что поскольку документы распределяются равномерно по фрагментам по умолчанию, статистика индекса должна быть очень похожа, и оценки будут работать как ожидается. Однако в случае, если вы:
- используете маршрутизацию во время индексации,
- запрашиваете несколько индексов,
- или у вас слишком мало данных в индексе
то велика вероятность, что все фрагменты, участвующие в запросе на поиск, не будут иметь похожей статистики индекса, и релевантность может быть низкой.
Если у вас небольшой набор данных, самый простой способ решения этой проблемы — индексировать всё в индекс с одним фрагментом (index.number_of_shards: 1), что является значением по умолчанию. Тогда статистика индекса будет одинаковой для всех документов, и оценки будут согласованными.
В противном случае рекомендуемый способ решения этой проблемы — использовать тип поиска dfs_query_then_fetch. Это позволит Elasticsearch выполнить начальный обмен данными со всеми вовлечёнными фрагментами, запросив у них их статистику индекса относительно запроса, затем координирующий узел объединит эту статистику и отправит объединённую статистику вместе с запросом при запросе фрагментам выполнить фазу query, чтобы фрагменты могли использовать эту глобальную статистику вместо собственной статистики для расчёта оценок.
В большинстве случаев эта дополнительная поездка должна быть очень быстрой. Однако в случае, если ваш запрос содержит очень большое количество полей/терминов или запросы с размытыми соответствиями, будьте осторожны, что сбор статистики сам по себе может быть не быстрым, так как все термины должны быть найдены в словарях терминов для поиска статистики.
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/consistent-scoring.html