Запрос с подсчетом баллов по скрипту
Использует скрипт для задания пользовательских баллов возвращаемым документам.
Запрос script_score полезен, например, если функция подсчета баллов является ресурсоемкой, и вам нужно вычислить баллы только для отфильтрованного набора документов.
Пример запроса
Следующий script_score запрос присваивает каждому возвращаемому документу балл, равный значению поля my-int, деленному на 10.
GET /_search
{
"query": {
"script_score": {
"query": {
"match": { "message": "elasticsearch" }
},
"script": {
"source": "doc['my-int'].value / 10 "
}
}
}
} Параметры верхнего уровня для запроса script_score
-
query - (Обязательный, объект запроса) Запрос, используемый для возвращения документов.
-
script -
(Обязательный, объект скрипта) Скрипт, используемый для вычисления баллов документов, возвращаемых запросом
query.Окончательные баллы релевантности от запроса
script_scoreне могут быть отрицательными. Для поддержки определенных оптимизаций поиска, Lucene требует, чтобы баллы были положительными или0. -
min_score - (Необязательно, число с плавающей точкой) Документы с баллом, меньшим этого числа с плавающей точкой, исключаются из результатов поиска.
-
boost - (Необязательно, число с плавающей точкой) Баллы документов, полученные запросом
script, умножаются наboostдля получения окончательных баллов документов. По умолчанию1.0.
Примечания
Использование баллов релевантности в скрипте
Внутри скрипта вы можете обратиться к переменной _score, которая представляет собой текущий балл релевантности документа.
Предопределенные функции
Вы можете использовать любые доступные функции painless в вашем скрипте script. Вы также можете использовать следующие предопределенные функции для настройки подсчета баллов:
Рекомендуется использовать эти предопределенные функции вместо написания своих. Эти функции используют преимущества эффективности внутренних механизмов Elasticsearch.
Насыщение
saturation(value,k) = value/(k + value)
"script" : {
"source" : "saturation(doc['my-int'].value, 1)"
} Сигмоида
sigmoid(value, k, a) = value^a/ (k^a + value^a)
"script" : {
"source" : "sigmoid(doc['my-int'].value, 2, 1)"
} Случайная функция подсчета баллов
Функция random_score генерирует баллы, равномерно распределенные от 0 до, но не включая 1.
Функция randomScore имеет следующий синтаксис: randomScore(<seed>, <fieldName>). Она имеет обязательный параметр - seed как целое значение и необязательный параметр - fieldName как строковое значение.
"script" : {
"source" : "randomScore(100, '_seq_no')"
} Если параметр fieldName опущен, внутренние идентификаторы документов Lucene будут использоваться в качестве источника случайности. Это очень эффективно, но, к сожалению, не воспроизводимо, так как документы могут быть переиндексированы во время слияний.
"script" : {
"source" : "randomScore(100)"
} Обратите внимание, что документы в одном фрагменте, имеющие одинаковое значение для поля, получат одинаковый балл, поэтому обычно желательно использовать поле, имеющее уникальные значения для всех документов в фрагменте. Хороший выбор по умолчанию — использовать поле _seq_no, единственным недостатком которого является то, что баллы изменятся, если документ будет обновлен, так как операции обновления также обновляют значение поля _seq_no.
Функции затухания для числовых полей
Вы можете прочитать больше о функциях затухания здесь.
-
double decayNumericLinear(double origin, double scale, double offset, double decay, double docValue) -
double decayNumericExp(double origin, double scale, double offset, double decay, double docValue) -
double decayNumericGauss(double origin, double scale, double offset, double decay, double docValue)
"script" : {
"source" : "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)",
"params": {
"origin": 20,
"scale": 10,
"decay" : 0.5,
"offset" : 0
}
} | Использование |
Функции затухания для геополей
-
double decayGeoLinear(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue) -
double decayGeoExp(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue) -
double decayGeoGauss(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)
"script" : {
"source" : "decayGeoExp(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
"params": {
"origin": "40, -70.12",
"scale": "200km",
"offset": "0km",
"decay" : 0.2
}
} Функции затухания для полей даты
-
double decayDateLinear(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate) -
double decayDateExp(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate) -
double decayDateGauss(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)
"script" : {
"source" : "decayDateGauss(params.origin, params.scale, params.offset, params.decay, doc['date'].value)",
"params": {
"origin": "2008-01-01T01:00:00Z",
"scale": "1h",
"offset" : "0",
"decay" : 0.5
}
} Функции затухания для дат ограничены датами в формате по умолчанию и часовом поясе по умолчанию. Также не поддерживаются вычисления с now.
Функции для векторных полей
Функции для векторных полей доступны через запрос script_score.
Разрешить ресурсоемкие запросы
Запросы с подсчетом баллов по скрипту не будут выполняться, если search.allow_expensive_queries установлено в false.
Более быстрые альтернативы
Запрос с подсчетом баллов по скрипту вычисляет балл для каждого соответствующего документа или результата. Существуют более быстрые типы запросов, которые могут эффективно пропускать неконкурентные результаты:
- Если вы хотите повысить приоритет документов по некоторым статическим полям, используйте запрос
rank_feature. - Если вы хотите повысить приоритет документов, расположенных ближе к определенной дате или географической точке, используйте запрос
distance_feature.
Переход от запроса function score
Рекомендуется использовать запрос script_score вместо запроса function_score для простоты запроса script_score.
Вы можете реализовать следующие функции запроса function_score с помощью запроса script_score:
script_score
То, что вы использовали в script_score запроса Function Score, можно скопировать в запрос Script Score. Здесь никаких изменений не требуется.
weight
Функцию weight можно реализовать в запросе Script Score с помощью следующего скрипта:
"script" : {
"source" : "params.weight * _score",
"params": {
"weight": 2
}
} random_score
Используйте функцию randomScore, как описано в функции рандомизированного подсчёта.
field_value_factor
Функцию field_value_factor можно легко реализовать с помощью скрипта:
"script" : {
"source" : "Math.log10(doc['field'].value * params.factor)",
"params" : {
"factor" : 5
}
} Для проверки наличия отсутствующего значения в документе вы можете использовать doc['field'].size() == 0. Например, этот скрипт будет использовать значение 1, если в документе отсутствует поле field:
"script" : {
"source" : "Math.log10((doc['field'].size() == 0 ? 1 : doc['field'].value()) * params.factor)",
"params" : {
"factor" : 5
}
} В этой таблице показано, как field_value_factor модификаторы могут быть реализованы с помощью скрипта:
| Модификатор | Реализация в Script Score |
|---|---|
| - |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
decay функции
Запрос script_score имеет эквивалентные функции убывания, которые можно использовать в скрипте.
Функции для векторных полей
При вычислении векторных функций все соответствующие документы линейно сканируются. Следовательно, ожидайте, что время запроса будет линейно возрастать с количеством соответствующих документов. По этой причине рекомендуется ограничивать количество соответствующих документов с помощью параметра query.
dense_vector функции
В этом списке представлены доступные векторные функции и методы доступа к векторам:
-
cosineSimilarity– вычисляет косинусное сходство -
dotProduct– вычисляет скалярное произведение -
l1norm– вычисляет расстояние L1 -
l2norm- вычисляет расстояние L2 -
doc[<field>].vectorValue– возвращает значение вектора в виде массива чисел с плавающей точкой -
doc[<field>].magnitude– возвращает величину вектора
Давайте создадим индекс с картой dense_vector и добавим в него пару документов.
PUT my-index-000001
{
"mappings": {
"properties": {
"my_dense_vector": {
"type": "dense_vector",
"dims": 3
},
"status" : {
"type" : "keyword"
}
}
}
}
PUT my-index-000001/_doc/1
{
"my_dense_vector": [0.5, 10, 6],
"status" : "published"
}
PUT my-index-000001/_doc/2
{
"my_dense_vector": [-0.5, 10, 10],
"status" : "published"
}
POST my-index-000001/_refresh Функция cosineSimilarity вычисляет меру косинусного сходства между заданным вектором запроса и векторами документов.
GET my-index-000001/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": "cosineSimilarity(params.query_vector, 'my_dense_vector') + 1.0",
"params": {
"query_vector": [4, 3.4, -0.2]
}
}
}
}
} | Для ограничения количества документов, к которым применяется вычисление оценки скрипта, укажите фильтр. | |
| Скрипт добавляет 1,0 к косинусному сходству, чтобы предотвратить получение отрицательной оценки. | |
| Для использования оптимизаций скрипта укажите вектор запроса в качестве параметра скрипта. |
Если у поля плотного вектора документа число измерений отличается от вектора запроса, будет выброшено исключение.
Функция dotProduct вычисляет меру скалярного произведения между заданным вектором запроса и векторами документов.
GET my-index-000001/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": """
double value = dotProduct(params.query_vector, 'my_dense_vector');
return sigmoid(1, Math.E, -value);
""",
"params": {
"query_vector": [4, 3.4, -0.2]
}
}
}
}
} | Использование стандартной функции сигмоиды предотвращает получение отрицательных оценок. |
Функция l1norm вычисляет расстояние L1 (расстояние Манхэттена) между заданным вектором запроса и векторами документов.
GET my-index-000001/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": "1 / (1 + l1norm(params.queryVector, 'my_dense_vector'))",
"params": {
"queryVector": [4, 3.4, -0.2]
}
}
}
}
} | В отличие от |
Функция l2norm вычисляет расстояние L2 (евклидово расстояние) между заданным вектором запроса и векторами документов.
GET my-index-000001/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": "1 / (1 + l2norm(params.queryVector, 'my_dense_vector'))",
"params": {
"queryVector": [4, 3.4, -0.2]
}
}
}
}
} Если для поля вектора документа, по которому выполняется векторная функция, нет значения, будет выброшено исключение.
Вы можете проверить, есть ли значение для поля my_vector в документе, используя doc['my_vector'].size() == 0. Ваш скрипт может выглядеть так:
"source": "doc['my_vector'].size() == 0 ? 0 : cosineSimilarity(params.queryVector, 'my_vector')"
Рекомендуемый способ доступа к плотным векторам — использование функций cosineSimilarity, dotProduct, l1norm или l2norm. Однако для пользовательских сценариев вы можете напрямую получить доступ к значениям плотных векторов с помощью следующих функций:
-
doc[<field>].vectorValue– возвращает значение вектора в виде массива чисел с плавающей точкой -
doc[<field>].magnitude– возвращает величину вектора как число с плавающей точкой (для векторов, созданных до версии 7.5, величина не хранится. Поэтому эта функция вычисляет её заново каждый раз при вызове).
Например, скрипт ниже реализует косинусное сходство, используя эти две функции:
GET my-index-000001/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": """
float[] v = doc['my_dense_vector'].vectorValue;
float vm = doc['my_dense_vector'].magnitude;
float dotProduct = 0;
for (int i = 0; i < v.length; i++) {
dotProduct += v[i] * params.queryVector[i];
}
return dotProduct / (vm * (float) params.queryVectorMag);
""",
"params": {
"queryVector": [4, 3.4, -0.2],
"queryVectorMag": 5.25357
}
}
}
}
}
sparse_vector функции
Устарело в 7.6.
Тип sparse_vector устарел и будет удален в версии 8.0.
Давайте создадим индекс с картой sparse_vector и добавим в него пару документов.
PUT my_sparse_index
{
"mappings": {
"properties": {
"my_sparse_vector": {
"type": "sparse_vector"
},
"status" : {
"type" : "keyword"
}
}
}
} PUT my_sparse_index/_doc/1
{
"my_sparse_vector": {"2": 1.5, "15" : 2, "50": -1.1, "4545": 1.1},
"status" : "published"
}
PUT my_sparse_index/_doc/2
{
"my_sparse_vector": {"2": 2.5, "10" : 1.3, "55": -2.3, "113": 1.6},
"status" : "published"
}
POST my_sparse_index/_refresh Функция cosineSimilaritySparse вычисляет косинусное сходство между заданным вектором запроса и векторами документов.
GET my_sparse_index/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": "cosineSimilaritySparse(params.query_vector, 'my_sparse_vector') + 1.0",
"params": {
"query_vector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
}
}
}
}
} Функция dotProductSparse вычисляет скалярное произведение между заданным вектором запроса и векторами документов.
GET my_sparse_index/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": """
double value = dotProductSparse(params.query_vector, 'my_sparse_vector');
return sigmoid(1, Math.E, -value);
""",
"params": {
"query_vector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
}
}
}
}
} Функция l1normSparse вычисляет расстояние L1 между заданным вектором запроса и векторами документов.
GET my_sparse_index/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": "1 / (1 + l1normSparse(params.queryVector, 'my_sparse_vector'))",
"params": {
"queryVector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
}
}
}
}
} Функция l2normSparse вычисляет расстояние L2 между заданным вектором запроса и векторами документов.
GET my_sparse_index/_search
{
"query": {
"script_score": {
"query" : {
"bool" : {
"filter" : {
"term" : {
"status" : "published"
}
}
}
},
"script": {
"source": "1 / (1 + l2normSparse(params.queryVector, 'my_sparse_vector'))",
"params": {
"queryVector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
}
}
}
}
} Объяснение запроса
Использование запроса объяснения предоставляет объяснение того, как были вычислены части оценки. Запрос script_score может добавить своё объяснение, установив параметр explanation:
GET /my-index-000001/_explain/0
{
"query": {
"script_score": {
"query": {
"match": { "message": "elasticsearch" }
},
"script": {
"source": """
long count = doc['count'].value;
double normalizedCount = count / 10;
if (explanation != null) {
explanation.set('normalized count = count / 10 = ' + count + ' / 10 = ' + normalizedCount);
}
return normalizedCount;
"""
}
}
}
} Обратите внимание, что explanation будет null при использовании в обычном запросе _search, поэтому наличие условного блока — лучший подход.
© 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-script-score-query.html