Spec-Zone.ru › Elasticsearch 7
›Elasticsearch Guide [7.17] ›Query DSL ›Составные запросы

Запрос с оценкой функций

Функция 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 определяет, как вычисленные рейтинги комбинируются:

multiply

рейтинги умножаются (по умолчанию)

sum

рейтинги суммируются

avg

рейтинги усредняются

first

применяется первая функция, которая имеет соответствующий фильтр

max

используется максимальный рейтинг

min

используется минимальный рейтинг

Поскольку рейтинги могут быть на разных шкалах (например, от 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 определяет, как:

multiply

рейтинг запроса и рейтинг функции умножаются (по умолчанию)

replace

используется только рейтинг функции, рейтинг запроса игнорируется

sum

рейтинг запроса и рейтинг функции складываются

avg

среднее значение

max

максимальное значение из рейтинга запроса и рейтинга функции

min

минимальное значение из рейтинга запроса и рейтинга функции

По умолчанию, изменение рейтинга не изменяет, какие документы соответствуют запросу. Чтобы исключить документы, которые не соответствуют определённому порогу рейтинга, параметр 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 имеет несколько опций:

field

Поле, которое нужно извлечь из документа.

factor

Необязательный множитель для умножения значения поля, по умолчанию 1.

modifier

Модификатор, применяемый к значению поля, может быть одним из: none, log, log1p, log2p, ln, ln1p, ln2p, square, sqrt или reciprocal. По умолчанию none.

Модификатор Значение

none

Не применять никакого множителя к значению поля

log

Вычислить десятичный логарифм значения поля. Поскольку эта функция вернёт отрицательное значение и вызовет ошибку при использовании для значений между 0 и 1, рекомендуется использовать log1p вместо этого.

log1p

Добавить 1 к значению поля и вычислить десятичный логарифм

log2p

Добавить 2 к значению поля и вычислить десятичный логарифм

ln

Вычислить натуральный логарифм значения поля. Поскольку эта функция вернёт отрицательное значение и вызовет ошибку при использовании для значений между 0 и 1, рекомендуется использовать ln1p вместо этого.

ln1p

Добавить 1 к значению поля и вычислить натуральный логарифм

ln2p

Добавить 2 к значению поля и вычислить натуральный логарифм

square

Возвести значение поля в квадрат (умножить его на себя)

sqrt

Вычислить квадратный корень из значения поля

reciprocal

Вычислить обратную величину значения поля, то же, что и 1/x, где x - значение поля

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
    }
}

DECAY_FUNCTION должна быть одной из linear, exp или gauss.

Указанное поле должно быть числовым, датой или геополевым.

В приведенном выше примере поле является geo_point, а начало координат можно указать в формате геокоординат. scale и offset в этом случае должны быть указаны с единицей измерения. Если ваше поле — поле даты, вы можете задать scale и offset как дни, недели и так далее. Пример:

GET /_search
{
  "query": {
    "function_score": {
      "gauss": {
        "@timestamp": {
          "origin": "2013-09-17", 
          "scale": "10d",
          "offset": "5d",         
          "decay": 0.5            
        }
      }
    }
  }
}

Формат даты начального значения зависит от format, определенного в вашей настройке. Если вы не определите начальное значение, будет использоваться текущее время.

Параметры offset и decay являются необязательными.

origin

Точка начала координат, используемая для вычисления расстояния. Для числового поля должно быть указано число, для полей даты — дата, для геополей — геокоординаты. Требуется для геополей и числовых полей. Для полей даты значение по умолчанию — now. Поддерживается математика дат (например, now-1h) для начального значения.

scale

Требуется для всех типов. Определяет расстояние от начала координат + смещение, при котором вычисленная оценка будет равна параметру decay. Для геополей: может быть определено как число + единица измерения (1км, 12м,…​). Единица измерения по умолчанию — метры. Для полей даты: может быть определено как число + единица измерения ("1ч", "10д",…​). Единица измерения по умолчанию — миллисекунды. Для числового поля: любое число.

offset

Если определено offset, функция затухания будет вычислять функцию затухания только для документов, расстояние до которых больше, чем заданное offset. Значение по умолчанию — 0.

decay

Параметр decay определяет, как документы оцениваются на расстоянии, заданном в scale. Если decay не определено, документы на расстоянии scale будут оцениваться в 0,5.

В первом примере документы могут представлять отели и содержать геолокационное поле. Вы хотите вычислить функцию затухания в зависимости от того, как далеко отель находится от заданного местоположения. Вы, возможно, не сразу поймёте, какую шкалу выбрать для функции Гаусса, но можете сказать что-то вроде: «На расстоянии 2 км от желаемого местоположения оценка должна быть уменьшена до одной трети». Затем параметр «масштаб» будет автоматически скорректирован, чтобы гарантировать, что функция оценки вычисляет оценку 0,33 для отелей, удалённых на 2 км от желаемого местоположения.

Во втором примере документы со значением поля между 2013-09-12 и 2013-09-22 получат вес 1,0, а документы, удалённые от этой даты на 15 дней, — вес 0,5.

Поддерживаемые функции затухания

DECAY_FUNCTION определяет форму затухания:

gauss

Нормальное затухание, вычисляемое как:

Gaussian

где sigma вычисляется для обеспечения того, чтобы оценка принимала значение decay на расстоянии scale от origin+-offset

sigma calc

См. Нормальное затухание, ключевое слово gauss для графиков, демонстрирующих кривую, созданную функцией gauss.

exp

Экспоненциальное затухание, вычисляемое как:

Exponential

где параметр lambda снова вычисляется для обеспечения того, чтобы оценка принимала значение decay на расстоянии scale от origin+-offset

lambda calc

См. Экспоненциальное затухание, ключевое слово exp для графиков, демонстрирующих кривую, созданную функцией exp.

linear

Линейное затухание, вычисляемое как:

Linear.

где параметр s снова вычисляется для обеспечения того, чтобы оценка принимала значение decay на расстоянии scale от origin+-offset

s calc

В отличие от нормального и экспоненциального затухания, эта функция фактически устанавливает оценку в 0, если значение поля превышает вдвое заданное пользователем значение масштаба.

Для отдельных функций три функции затухания вместе с их параметрами можно визуализировать следующим образом (в этом примере поле называется «возраст»):

decay 2d

Поля с несколькими значениями

Если поле, используемое для вычисления затухания, содержит несколько значений, по умолчанию выбирается значение, наиболее близкое к началу координат, для определения расстояния. Это можно изменить, установив multi_value_mode.

min

Расстояние — минимальное расстояние

max

Расстояние — максимальное расстояние

avg

Расстояние — среднее расстояние

sum

Расстояние — сумма всех расстояний

Пример:

    "DECAY_FUNCTION": {
        "FIELD_NAME": {
              "origin": ...,
              "scale": ...
        },
        "multi_value_mode": "avg"
    }

Подробный пример

Предположим, вы ищете отель в определенном городе. Ваш бюджет ограничен. Кроме того, вы хотите, чтобы отель был недалеко от центра города, поэтому чем дальше отель от желаемого места, тем меньше вероятность, что вы забронируете его.

Вы хотите, чтобы результаты поиска, соответствующие вашим критериям (например, "отель, Нэнси, некурящий"), были оценены с учетом расстояния до центра города и цены.

Интуитивно вы хотите определить центр города как начало отсчёта и, возможно, вы готовы пройти пешком 2 км до центра города от отеля.
В этом случае ваше начало отсчёта для поля местоположения — центр города, а масштаб — около 2 км.

Если ваш бюджет ограничен, вы, вероятно, предпочтёте что-то дешёвое, чем что-то дорогое. Для поля цены начало отсчёта будет 0 евро, а масштаб зависит от того, сколько вы готовы платить, например, 20 евро.

В этом примере поля могут называться "цена" для цены отеля и "местоположение" для координат этого отеля.

Функция для price в этом случае будет

"gauss": { 
    "price": {
          "origin": "0",
          "scale": "20"
    }
}

Эта функция затухания также может быть linear или exp.

и для location:

"gauss": { 
    "location": {
          "origin": "11, 12",
          "scale": "2km"
    }
}

Эта функция затухания также может быть linear или exp.

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

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 в качестве функции затухания в приведённом выше примере контурная и поверхностная диаграммы множителя выглядят следующим образом:

cd0e18a6 e898 11e2 9b3c f0145078bd6f
ec43c928 e898 11e2 8e0d f3c4519dbd89

Предположим, что результаты вашего исходного поиска соответствуют трём отелям:

  • "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 в качестве функции затухания в приведённом выше примере контурная и поверхностная диаграммы множителя выглядят следующим образом:

082975c0 e899 11e2 86f7 174c3a729d64
0b606884 e899 11e2 907b aefc77eefef6

Линейное затухание, ключевое слово linear

При выборе linear в качестве функции затухания в приведённом выше примере контурная и поверхностная диаграммы множителя выглядят следующим образом:

1775b0ca e899 11e2 9f4a 776b406305c6
19d8b1aa e899 11e2 91bc 6b0553e8d722

Поддерживаемые поля для функций затухания

Поддерживаются только числовые, датированные и геокоординатные поля.

Что делать, если поле отсутствует?

Если числовое поле отсутствует в документе, функция вернёт 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API