ElasticSearch: странное поведение поиска при использовании анализатора снежного кома
Допустим, у меня есть индекс ElasticSearch, определенный следующим образом:
curl -XPUT 'http://localhost:9200/test' -d '{
"mappings": {
"example": {
"properties": {
"text": {
"type": "string",
"analyzer": "snowball"
}
}
}
}
}'
curl -XPUT 'http://localhost:9200/test/example/1' -d '{
"text": "foo bar organization"
}'
Когда я ищу "foo организаций" с анализатором снежного кома, оба ключевых слова соответствуют ожидаемым:
curl -XGET http://localhost:9200/test/example/_search -d '{
"query": {
"text": {
"_all": {
"query": "foo organizations",
"analyzer": "snowball"
}
}
},
"highlight": {
"fields": {
"text": {}
}
}
}'
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.015912745,
"hits": [
{
"_index": "test",
"_type": "example",
"_id": "1",
"_score": 0.015912745,
"_source": {
"text": "foo bar organization"
},
"highlight": {
"text": [
"<em>foo</em> bar <em>organization</em>"
]
}
}
]
}
}
Но когда я ищу только "организации", я не получаю никаких результатов, что очень странно:
curl -XGET http://localhost:9200/test/example/_search -d '{
"query": {
"text": {
"_all": {
"query": "organizations",
"analyzer": "snowball"
}
}
},
"highlight": {
"fields": {
"text": {}
}
}
}'
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
Тем не менее, если я ищу "бары", он все равно попадает:
curl -XGET http://localhost:9200/test/example/_search -d '{
"query": {
"text": {
"_all": {
"query": "bars",
"analyzer": "snowball"
}
}
},
"highlight": {
"fields": {
"text": {}
}
}
}'
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.10848885,
"hits": [
{
"_index": "test",
"_type": "example",
"_id": "1",
"_score": 0.10848885,
"_source": {
"text": "foo bar organization"
},
"highlight": {
"text": [
"foo <em>bar</em> organization"
]
}
}
]
}
}
Я предполагаю, что разница между "баром" и "организацией" заключается в том, что "организация" связана с "органом", а "бар" - с самим собой. Но как мне получить правильное поведение, чтобы второй поиск попадал?
2 ответа
Текст "организация foo bar" индексируется дважды - в тексте поля и в поле _all. Текст поля использует анализатор снежного кома, а поле _all использует стандартный анализатор. Поэтому после анализа тестовой записи поле _all содержит токены: "foo", "bar" и "organization". При поиске указанный анализатор снежного кома преобразует "foo" в "foo", "bars" в "bar", а "organization" в "organ". Таким образом, слова "foo" и "bars" в запросе соответствуют записи теста, а термин "организация" - нет. Выделение выполняется для каждого поля независимо от поиска, поэтому слово "организация" выделяется в первом результате.
Лучше использовать анализатор во время индексации, чем во время поиска. Отобразите текстовое поле в анализатор снежного кома, а затем индексируйте. Это создаст несколько токенов для организации, в которую входят организации. Это работает для меня