Есть несколько способов сделать это. Есть более чистый подход с несколькими запросами (с использованием Multi API поиска) и более сложный подход с одним запросом (с использованием _ 1_ query). Позвольте мне объяснить вам, как это сделать.
Более чистый подход с использованием _msearch
Проще говоря, _msearch
позволяет сделать один HTTP-запрос с несколькими запросами Elasticsearch в нем. Я бы посоветовал разбить исходный запрос на несколько запросов и отсортировать их по дате. Этот подход будет проще, потому что, как я покажу вам позже, включение этого в один запрос потребует модификации оценки, что не так просто.
Вы также можете сделать несколько запросов без использования _msearch
, в зависимости от того, что считаете нужным.
Почему не сработали другие подходы?
Вы уже знаете о простой настройке оценки за счет усиления одних полей над другими, как в этом примере _ 5_ запрос:
POST /myscores/_search
{
"query": {
"multi_match": {
"query": "beyond",
"fields": ["field_A^3", "filed_B^2", "Field_C^1"]
}
}
}
Это просто возьмет результат совпадения, умноженный на 3, если он совпадает с field_A
, умноженный на 2, если filed_B
, и т. Д.
Теперь оценка - это просто реальное положительное число, и оно должно представлять, где в списке сопоставленных результатов мы должны разместить конкретный документ.
Как вы уже пробовали, если вы попросите Elasticsearch использовать updated_time
в качестве меры сортировки, он проигнорирует результат сопоставления, что нежелательно.
Предложение товарища Гиббса также, похоже, не сработало, потому что использование сортировки по _score
, а затем по updated_time
(или наоборот ) игнорировал тот или иной вариант.
Есть ли способ объединить _score
и updated_time
?
Есть, попробуем использовать function_score
:
POST /myscores/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "beyond",
"fields": [
"field_A^3",
"filed_B^2",
"Field_C"
]
}
},
"score_mode": "max",
"boost_mode": "multiply", <=== 2
"field_value_factor": { <=== 1
"field": "updated_time",
"factor": 0.00000000001,
"missing": 1
}
}
}
}
function_score
позволяет вы можете точно настроить оценку запроса.
Мы берем multi_match
запрос, с которым мы уже знакомы из раздела выше, и пытаемся изменить его.
Во-первых, мы знаем, что хотим принять во внимание updated_time
. Мы используем _ 19_ как функция для изменения оценки (точка 1 в запросе выше).
Теперь мы говорим ему умножить значение updated_time
на оценку запроса - установив boost_mode
на multiply
(пункт 2).
Выполнение этого запроса даст примерно следующее:
"hits": [
{
...
"_score": 43.121338,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "**beyond** filed_A",
"filed_B": "The properties in Japan is high",
"Field_C": "Test description for filed_A"
}
},
{
...
"_score": 43.048275,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Slovakia beyond",
"filed_B": "The properties in Slovakia are beyound...",
"Field_C": "Once you fix the relevance then sorting should work correctly."
}
},
{
...
"_score": 29.028637,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search term in filed_B",
"Field_C": "Test description for filed_B"
}
},
{
...
"_score": 24.44329,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search term in filed_B Test for Feb",
"Field_C": "Test description for filed_B test for Feb"
}
},
{
...
"_score": 23.517717,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Search Term filed_C",
"filed_B": " is the search term for lowest column",
"Field_C": "**beyond** Test description for filed_C "
}
}
]
Обратите внимание, что оценки field_A
совпадений близки друг к другу, но немного отличаются от оценок filed_B
.
Также обратите внимание, что заказ updated_time
является самым последним первым; Сейчас мы обратимся к обратному порядку.
Как использовать updated_time
для сортировки в обратном порядке?
field_value_factor
позволяет умножить исходное значение из поля на некоторый коэффициент.
Внутри Elasticsearch хранит даты как временные метки unix. Это целое число из 10 цифр, что буквально на ~ 10 порядков больше, чем оценка ES, которую я получил. Поэтому я решил сделать их сопоставимого порядка:
"field_value_factor": {
"field": "updated_time",
"factor": 0.00000000001,
"missing": 1
}
Теперь это дает нам эквивалент SORT BY updated_time DESC
:
Feb 2020
Jan 2020
Но что, если нам нужно, чтобы это было SORT BY updated_time ASC
?
Jan 2020
Feb 2020
Мы не можем умножать на отрицательный коэффициент, потому что оценки в Elasticsearch должны быть положительными действительными числами.
Вместо этого мы можем изменить исходное значение с помощью 1/x
, как здесь:
"field_value_factor": {
"field": "updated_time",
"factor": 0.00000000001,
"missing": 1,
"modifier": "reciprocal" <=== 1/x
}
Это, наконец, даст нам порядок, о котором вы просили в вопросе:
"hits": [
{
...
"_score": 0.17285699,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Slovakia beyond",
"filed_B": "The properties in Slovakia are beyound...",
"Field_C": "Once you fix the relevance then sorting should work correctly."
}
},
{
...
"_score": 0.1725641,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "**beyond** filed_A",
"filed_B": "The properties in Japan is high",
"Field_C": "Test description for filed_A"
}
},
{
...
"_score": 0.116562225,
"_source": {
"updated_time": "2020-01-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search term in filed_B",
"Field_C": "Test description for filed_B"
}
},
{
...
"_score": 0.0978178,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Test filed_B",
"filed_B": "**beyond** is search term in filed_B Test for Feb",
"Field_C": "Test description for filed_B test for Feb"
}
},
{
...
"_score": 0.09411382,
"_source": {
"updated_time": "2020-02-04T01:00:06.870000Z",
"field_A": "Search Term filed_C",
"filed_B": " is the search term for lowest column",
"Field_C": "**beyond** Test description for filed_C "
}
}
Как это сделать на Java?
Хотя я не могу предоставить вам готовый код, я считаю, что вы можете начать с FunctionScoreBuilder и попробуйте интегрировать его с существующим кодом.
Надеюсь это поможет!
person
Nikolay Vasiliev
schedule
19.05.2020
document_date
- 2018 год, должно ли оно быть в результирующем наборе выше, чемField_B, 2020
? - person Nikolay Vasiliev   schedule 17.05.2020