Получение согласованных оценок
Тот факт, что 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/8.17/consistent-scoring.html