Запрос с оценкой функций
Функция function_score позволяет изменять рейтинг документов, которые извлекаются запросом. Это может быть полезно, например, если функция вычисления рейтинга вычислительно затратна, и достаточно вычислить рейтинг на отфильтрованном наборе документов.
Для использования function_score пользователю необходимо определить запрос и одну или несколько функций, которые вычисляют новый рейтинг для каждого документа, возвращённого запросом.
function_score может использоваться с одной функцией следующим образом:
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"random_score": {},
"boost_mode": "multiply"
}
}
} | См. Функцию вычисления рейтинга для списка поддерживаемых функций. |
Кроме того, можно комбинировать несколько функций. В этом случае можно дополнительно выбрать применение функции только в том случае, если документ соответствует заданному фильтрующему запросу
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"functions": [
{
"filter": { "match": { "test": "bar" } },
"random_score": {},
"weight": 23
},
{
"filter": { "match": { "test": "cat" } },
"weight": 42
}
],
"max_boost": 42,
"score_mode": "max",
"boost_mode": "multiply",
"min_score": 42
}
}
} | Усиление для всего запроса. | |
| См. Функцию вычисления рейтинга для списка поддерживаемых функций. |
Рейтинги, полученные фильтрующим запросом каждой функции, не имеют значения.
Если фильтр не задан для функции, это эквивалентно указанию "match_all": {}
Сначала каждый документ оценивается заданными функциями. Параметр score_mode определяет, как вычисленные рейтинги комбинируются:
| | рейтинги умножаются (по умолчанию) |
| | рейтинги суммируются |
| | рейтинги усредняются |
| | применяется первая функция, которая имеет соответствующий фильтр |
| | используется максимальный рейтинг |
| | используется минимальный рейтинг |
Поскольку рейтинги могут быть на разных шкалах (например, от 0 до 1 для функций затухания, но произвольные для field_value_factor), а также потому, что иногда желательно разное влияние функций на рейтинг, рейтинг каждой функции может быть скорректирован с помощью пользовательского weight. weight может быть определён для каждой функции в массиве functions (пример выше) и умножается на рейтинг, вычисленный соответствующей функцией. Если вес задан без объявления других функций, weight действует как функция, которая просто возвращает weight.
В случае, если score_mode установлено в значение avg, индивидуальные рейтинги будут объединены взвешенным средним. Например, если две функции возвращают рейтинг 1 и 2, а их соответствующие веса 3 и 4, то их рейтинги будут объединены как (1*3+2*4)/(3+4), а не как (1*3+2*4)/2.
Новый рейтинг может быть ограничен, чтобы не превышать определённого предела, установив параметр max_boost. Значение по умолчанию для max_boost равно FLT_MAX.
Новое вычисленное значение рейтинга комбинируется с рейтингом запроса. Параметр boost_mode определяет, как:
| | рейтинг запроса и рейтинг функции умножаются (по умолчанию) |
| | используется только рейтинг функции, рейтинг запроса игнорируется |
| | рейтинг запроса и рейтинг функции складываются |
| | среднее значение |
| | максимальное значение из рейтинга запроса и рейтинга функции |
| | минимальное значение из рейтинга запроса и рейтинга функции |
По умолчанию, изменение рейтинга не изменяет, какие документы соответствуют запросу. Чтобы исключить документы, которые не соответствуют определённому порогу рейтинга, параметр min_score может быть установлен на желаемый порог рейтинга.
Для работы min_score необходимо, чтобы все документы, возвращаемые запросом, были оценены, а затем отфильтрованы по одному.
Запрос function_score предоставляет несколько типов функций вычисления рейтинга.
-
script_score -
weight -
random_score -
field_value_factor - функции затухания:
gauss,linear,exp
Скрипт вычисления рейтинга
Функция script_score позволяет обернуть другой запрос и настроить оценку его, необязательно с вычислением, полученным из других числовых значений поля в документе с помощью скриптового выражения. Вот простой пример:
GET /_search
{
"query": {
"function_score": {
"query": {
"match": { "message": "elasticsearch" }
},
"script_score": {
"script": {
"source": "Math.log(2 + doc['my-int'].value)"
}
}
}
}
} Во всех документах Elasticsearch все рейтинги являются положительными 32-битными числами с плавающей запятой.
Если функция script_score производит рейтинг с большей точностью, он преобразуется в ближайшее 32-битное число с плавающей запятой.
Аналогично, рейтинги должны быть неотрицательными. В противном случае Elasticsearch вернёт ошибку.
В дополнение к различным скриптовым значениям и выражениям поля, параметр скрипта _score может быть использован для получения рейтинга на основе обернутого запроса.
Компиляция скриптов кэшируется для более быстрого выполнения. Если скрипт должен учитывать параметры, предпочтительно повторно использовать тот же скрипт и предоставить ему параметры:
GET /_search
{
"query": {
"function_score": {
"query": {
"match": { "message": "elasticsearch" }
},
"script_score": {
"script": {
"params": {
"a": 5,
"b": 1.2
},
"source": "params.a / Math.pow(params.b, doc['my-int'].value)"
}
}
}
}
} Обратите внимание, что в отличие от запроса custom_score, рейтинг запроса умножается на результат вычисления рейтинга скриптом. Если вы хотите запретить это, установите "boost_mode": "replace"
Вес
Рейтинг weight позволяет вам умножить рейтинг на предоставленное значение weight. Иногда это может быть желательно, так как значения усиления, установленные для определенных запросов, нормализуются, в то время как для этой функции вычисления рейтинга это не так. Значение числового типа - float.
"weight" : number
Случайный
random_score генерирует рейтинги, равномерно распределённые от 0 до, но не включая 1. По умолчанию он использует внутренние идентификаторы документов Lucene в качестве источника случайности, что очень эффективно, но, к сожалению, не воспроизводимо, так как документы могут быть переименованы слияниями.
В случае, если вы хотите, чтобы рейтинги были воспроизводимыми, можно предоставить seed и field. Конечный рейтинг будет затем вычислен на основе этого зерна, минимального значения field для рассматриваемого документа и соли, вычисленной на основе имени индекса и идентификатора фрагмента, так что документы с одинаковым значением, но хранящиеся в разных индексах, получают разные рейтинги. Обратите внимание, что документы, которые находятся в одном фрагменте и имеют одинаковое значение для field, однако, получат одинаковый рейтинг, поэтому обычно желательно использовать поле, имеющее уникальные значения для всех документов. Хорошим выбором по умолчанию может быть использование поля _seq_no, единственным недостатком которого является то, что рейтинги изменятся, если документ обновляется, поскольку операции обновления также обновляют значение поля _seq_no.
Было возможно установить зерно без установки поля, но это устарело, так как это требует загрузки fielddata для поля _id, что потребляет много памяти.
GET /_search
{
"query": {
"function_score": {
"random_score": {
"seed": 10,
"field": "_seq_no"
}
}
}
} Значение поля factor
Функция field_value_factor позволяет использовать поле из документа для влияния на рейтинг. Она похожа на использование функции script_score, но избегает накладных расходов на скриптинг. Если используется для многозначного поля, в расчётах используется только первое значение поля.
Например, представьте, что у вас есть документ, индексированный с числовым полем my-int, и вы хотите повлиять на рейтинг документа с этим полем. Пример использования:
GET /_search
{
"query": {
"function_score": {
"field_value_factor": {
"field": "my-int",
"factor": 1.2,
"modifier": "sqrt",
"missing": 1
}
}
}
} Что переведётся в следующую формулу для расчёта рейтинга:
sqrt(1.2 * doc['my-int'].value)
Функция field_value_factor имеет несколько опций:
| | Поле, которое нужно извлечь из документа. |
| | Необязательный множитель для умножения значения поля, по умолчанию |
| | Модификатор, применяемый к значению поля, может быть одним из: |
| Модификатор | Значение |
|---|---|
| Не применять никакого множителя к значению поля |
| Вычислить десятичный логарифм значения поля. Поскольку эта функция вернёт отрицательное значение и вызовет ошибку при использовании для значений между 0 и 1, рекомендуется использовать |
| Добавить 1 к значению поля и вычислить десятичный логарифм |
| Добавить 2 к значению поля и вычислить десятичный логарифм |
| Вычислить натуральный логарифм значения поля. Поскольку эта функция вернёт отрицательное значение и вызовет ошибку при использовании для значений между 0 и 1, рекомендуется использовать |
| Добавить 1 к значению поля и вычислить натуральный логарифм |
| Добавить 2 к значению поля и вычислить натуральный логарифм |
| Возвести значение поля в квадрат (умножить его на себя) |
| Вычислить квадратный корень из значения поля |
| Вычислить обратную величину значения поля, то же, что и |
-
missing - Значение, используемое, если в документе нет такого поля. Модификатор и множитель всё равно применяются к нему, как будто оно было прочитано из документа.
Значения, полученные функцией field_value_score, должны быть неотрицательными, иначе будет выброшена ошибка. Модификаторы log и ln дадут отрицательные значения, если использованы для значений между 0 и 1. Убедитесь, что вы ограничили значения поля с помощью фильтра диапазона, или используйте log1p и ln1p.
Помните, что вычисление log() от 0 или квадратного корня из отрицательного числа является незаконной операцией, и будет выброшено исключение. Убедитесь, что вы ограничили значения поля с помощью фильтра диапазона, или используйте log1p и ln1p.
Функции затухания
Функции затухания оценивают документ с помощью функции, которая затухает в зависимости от расстояния числового значения поля документа от заданного пользователем начального значения. Это похоже на запрос по диапазону, но с плавными краями вместо прямоугольников.
Для использования оценки расстояния в запросе, содержащем числовые поля, пользователь должен определить origin и scale для каждого поля. origin необходим для определения «центральной точки», от которой вычисляется расстояние, а scale для определения скорости затухания. Функция затухания задается как
"DECAY_FUNCTION": {
"FIELD_NAME": {
"origin": "11, 12",
"scale": "2km",
"offset": "0km",
"decay": 0.33
}
} |
| |
| Указанное поле должно быть числовым, датой или геополевым. |
В приведенном выше примере поле является geo_point, а начало координат можно указать в формате геокоординат. scale и offset в этом случае должны быть указаны с единицей измерения. Если ваше поле — поле даты, вы можете задать scale и offset как дни, недели и так далее. Пример:
GET /_search
{
"query": {
"function_score": {
"gauss": {
"@timestamp": {
"origin": "2013-09-17",
"scale": "10d",
"offset": "5d",
"decay": 0.5
}
}
}
}
} | Формат даты начального значения зависит от | |
| Параметры |
| | Точка начала координат, используемая для вычисления расстояния. Для числового поля должно быть указано число, для полей даты — дата, для геополей — геокоординаты. Требуется для геополей и числовых полей. Для полей даты значение по умолчанию — |
| | Требуется для всех типов. Определяет расстояние от начала координат + смещение, при котором вычисленная оценка будет равна параметру |
| | Если определено |
| | Параметр |
В первом примере документы могут представлять отели и содержать геолокационное поле. Вы хотите вычислить функцию затухания в зависимости от того, как далеко отель находится от заданного местоположения. Вы, возможно, не сразу поймёте, какую шкалу выбрать для функции Гаусса, но можете сказать что-то вроде: «На расстоянии 2 км от желаемого местоположения оценка должна быть уменьшена до одной трети». Затем параметр «масштаб» будет автоматически скорректирован, чтобы гарантировать, что функция оценки вычисляет оценку 0,33 для отелей, удалённых на 2 км от желаемого местоположения.
Во втором примере документы со значением поля между 2013-09-12 и 2013-09-22 получат вес 1,0, а документы, удалённые от этой даты на 15 дней, — вес 0,5.
Поддерживаемые функции затухания
DECAY_FUNCTION определяет форму затухания:
-
gauss -
Нормальное затухание, вычисляемое как:
где
вычисляется для обеспечения того, чтобы оценка принимала значение
decayна расстоянииscaleотorigin+-offsetСм. Нормальное затухание, ключевое слово
gaussдля графиков, демонстрирующих кривую, созданную функциейgauss. -
exp -
Экспоненциальное затухание, вычисляемое как:
где параметр
снова вычисляется для обеспечения того, чтобы оценка принимала значение
decayна расстоянииscaleотorigin+-offsetСм. Экспоненциальное затухание, ключевое слово
expдля графиков, демонстрирующих кривую, созданную функциейexp. -
linear -
Линейное затухание, вычисляемое как:
.
где параметр
sснова вычисляется для обеспечения того, чтобы оценка принимала значениеdecayна расстоянииscaleотorigin+-offsetВ отличие от нормального и экспоненциального затухания, эта функция фактически устанавливает оценку в 0, если значение поля превышает вдвое заданное пользователем значение масштаба.
Для отдельных функций три функции затухания вместе с их параметрами можно визуализировать следующим образом (в этом примере поле называется «возраст»):
Поля с несколькими значениями
Если поле, используемое для вычисления затухания, содержит несколько значений, по умолчанию выбирается значение, наиболее близкое к началу координат, для определения расстояния. Это можно изменить, установив multi_value_mode.
| | Расстояние — минимальное расстояние |
| | Расстояние — максимальное расстояние |
| | Расстояние — среднее расстояние |
| | Расстояние — сумма всех расстояний |
Пример:
"DECAY_FUNCTION": {
"FIELD_NAME": {
"origin": ...,
"scale": ...
},
"multi_value_mode": "avg"
} Подробный пример
Предположим, вы ищете отель в определенном городе. Ваш бюджет ограничен. Кроме того, вы хотите, чтобы отель был недалеко от центра города, поэтому чем дальше отель от желаемого места, тем меньше вероятность, что вы забронируете его.
Вы хотите, чтобы результаты поиска, соответствующие вашим критериям (например, "отель, Нэнси, некурящий"), были оценены с учетом расстояния до центра города и цены.
Интуитивно вы хотите определить центр города как начало отсчёта и, возможно, вы готовы пройти пешком 2 км до центра города от отеля.
В этом случае ваше начало отсчёта для поля местоположения — центр города, а масштаб — около 2 км.
Если ваш бюджет ограничен, вы, вероятно, предпочтёте что-то дешёвое, чем что-то дорогое. Для поля цены начало отсчёта будет 0 евро, а масштаб зависит от того, сколько вы готовы платить, например, 20 евро.
В этом примере поля могут называться "цена" для цены отеля и "местоположение" для координат этого отеля.
Функция для price в этом случае будет
"gauss": {
"price": {
"origin": "0",
"scale": "20"
}
} | Эта функция затухания также может быть |
и для location:
"gauss": {
"location": {
"origin": "11, 12",
"scale": "2km"
}
} | Эта функция затухания также может быть |
Предположим, вы хотите умножить эти две функции на исходный балл, запрос будет выглядеть так:
GET /_search
{
"query": {
"function_score": {
"functions": [
{
"gauss": {
"price": {
"origin": "0",
"scale": "20"
}
}
},
{
"gauss": {
"location": {
"origin": "11, 12",
"scale": "2km"
}
}
}
],
"query": {
"match": {
"properties": "balcony"
}
},
"score_mode": "multiply"
}
}
} Далее мы покажем, как выглядит вычисленный балл для каждой из трёх возможных функций затухания.
Нормальное затухание, ключевое слово gauss
При выборе gauss в качестве функции затухания в приведённом выше примере контурная и поверхностная диаграммы множителя выглядят следующим образом:
Предположим, что результаты вашего исходного поиска соответствуют трём отелям:
- "Backback Nap"
- "Drink n Drive"
- "BnB Bellevue".
"Drink n Drive" находится довольно далеко от вашего определённого местоположения (почти 2 км) и не слишком дешёвый (около 13 евро), поэтому он получает низкий множитель 0,56. "BnB Bellevue" и "Backback Nap" оба находятся довольно близко к определённому местоположению, но "BnB Bellevue" дешевле, поэтому он получает множитель 0,86, а "Backpack Nap" — 0,66.
Экспоненциальное затухание, ключевое слово exp
При выборе exp в качестве функции затухания в приведённом выше примере контурная и поверхностная диаграммы множителя выглядят следующим образом:
Линейное затухание, ключевое слово linear
При выборе linear в качестве функции затухания в приведённом выше примере контурная и поверхностная диаграммы множителя выглядят следующим образом:
Поддерживаемые поля для функций затухания
Поддерживаются только числовые, датированные и геокоординатные поля.
Что делать, если поле отсутствует?
Если числовое поле отсутствует в документе, функция вернёт 1.
© 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/query-dsl-function-score-query.html