Смешивание точного поиска со стемингом
При создании приложения для поиска стеминг часто необходим, так как желательно, чтобы запрос на skiing соответствовал документам, содержащим ski или skis. Но что, если пользователь хочет искать именно skiing? Обычно для этого используется многопольное поле, чтобы один и тот же контент индексировался двумя разными способами:
PUT index
{
"settings": {
"analysis": {
"analyzer": {
"english_exact": {
"tokenizer": "standard",
"filter": [
"lowercase"
]
}
}
}
},
"mappings": {
"properties": {
"body": {
"type": "text",
"analyzer": "english",
"fields": {
"exact": {
"type": "text",
"analyzer": "english_exact"
}
}
}
}
}
}
PUT index/_doc/1
{
"body": "Ski resort"
}
PUT index/_doc/2
{
"body": "A pair of skis"
}
POST index/_refresh При такой настройке поиск ski по body вернёт оба документа:
GET index/_search
{
"query": {
"simple_query_string": {
"fields": [ "body" ],
"query": "ski"
}
}
} {
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 2,
"relation": "eq"
},
"max_score": 0.18232156,
"hits": [
{
"_index": "index",
"_type": "_doc",
"_id": "1",
"_score": 0.18232156,
"_source": {
"body": "Ski resort"
}
},
{
"_index": "index",
"_type": "_doc",
"_id": "2",
"_score": 0.18232156,
"_source": {
"body": "A pair of skis"
}
}
]
}
} С другой стороны, поиск ski по body.exact вернёт только документ 1, так как цепочка анализа body.exact не выполняет стеминг.
GET index/_search
{
"query": {
"simple_query_string": {
"fields": [ "body.exact" ],
"query": "ski"
}
}
} {
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.8025915,
"hits": [
{
"_index": "index",
"_type": "_doc",
"_id": "1",
"_score": 0.8025915,
"_source": {
"body": "Ski resort"
}
}
]
}
} Это не так просто предоставить конечным пользователям, поскольку нам нужно определить, ищет ли пользователь точное совпадение или нет, и перенаправить его на соответствующее поле. А что делать, если только некоторые части запроса нужно искать точно, а другие части должны учитывать стеминг?
К счастью, запросы query_string и simple_query_string имеют функцию, решающую эту проблему: quote_field_suffix. Это сообщает Elasticsearch, что слова, заключённые в кавычки, должны быть перенаправлены в другое поле, см. ниже:
GET index/_search
{
"query": {
"simple_query_string": {
"fields": [ "body" ],
"quote_field_suffix": ".exact",
"query": "\"ski\""
}
}
} {
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped" : 0,
"failed": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.8025915,
"hits": [
{
"_index": "index",
"_type": "_doc",
"_id": "1",
"_score": 0.8025915,
"_source": {
"body": "Ski resort"
}
}
]
}
} В данном случае, поскольку ski было заключено в кавычки, оно искалось в поле body.exact благодаря параметру quote_field_suffix, поэтому соответствовал только документ 1. Это позволяет пользователям смешивать точный поиск со стемингом по своему усмотрению.
Если выбранное поле в quote_field_suffix не существует, поиск вернётся к использованию поля по умолчанию для запроса.
© 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/mixing-exact-search-with-stemming.html