#amazon-web-services #elasticsearch #lucene #kibana #aws-elasticsearch
Вопрос:
Я пытаюсь запросить индекс для всех документов с соответствующими значениями в определенном текстовом поле Field_Name_1
и отфильтровать эти результаты, чтобы показывать только документы , Field_Name_2
поле которых имеет любое числовое значение в предоставленном списке, [1, 2, 3, 4, 5].
Проблема , с которой я сталкиваюсь, заключается в том, что запрос вернет документы, которые в некоторой степени соответствуют значению Field_Name_1
, но мне нужно возвращать только документы, которые Field_Name_1
точно соответствуют значению. Проведя исследование, я считаю, что мне следовало бы создать Field_Name_1
поле ключевого слова, а не текстовое поле, потому что мне никогда не понадобится запускать этот запрос, предоставляя точное полное значение Field_Name_1
.
Прав ли я, думая, что мне нужно создать новый индекс с Field_Name_1
заданным ключевым словом, а затем переиндексировать? Я раньше не переиндексировался, поэтому беспокоюсь о потере данных, если не сделаю это должным образом. Есть ли способ выполнить этот запрос с Field_Name_1
помощью текстового поля?
Это два запроса, которые я пробовал, но оба они возвращают одни и те же результаты. Единственное различие заключается в том, что первый запрос возвращает «max_score» 9,54, в то время как второй запрос возвращает «max_score» 0.
GET Index_Name/_search
{
"query": {
"bool": {
"must": {
"match": {
"Field_Name_1": "12345-1234-1234-1234-d123f123g123"
}
},
"filter": {
"terms": {
"Field_Name_2": [
1,
2,
3,
4,
5
]
}
}
}
},
"track_total_hits": true
}
GET Index_Name/_search
{
"query": {
"bool": {
"filter": [
{
"match": {
"Field_Name_1": "12345-1234-1234-1234-d123f123g123"
}
},
{
"terms": {
"Field_Name_2": [
1,
2,
3,
4,
5
]
}
}
]
}
},
"track_total_hits": true
}
Комментарии:
1. Можете ли вы поделиться отображением своего индекса и своей версии ES? curl -X «GET» «локальный хост:9200/yourindex/_mappings»
2. @JuanCarlosAlafita Конечно. Field_Name_1 выглядит так: «идентификатор хранилища» : { «тип» : «текст», «поля» : { «ключевое слово» : { «тип» : «ключевое слово», «ignore_above» : 256 } } } Все отображение индекса слишком велико, чтобы помещать его сюда.
Ответ №1:
Field_Name_1
Поле должно быть keyword
типа.
Это связано с тем, что Elasticsearch использует стандартный анализатор, если он не указан. Вы можете проверить токены, сгенерированные с помощью API анализа, как показано ниже —
GET /_analyze
{
"analyzer": "standard",
"text": "12345-1234-1234-1234-d123f123g123"
}
Сгенерированные токены будут
{
"tokens": [
{
"token": "12345",
"start_offset": 0,
"end_offset": 5,
"type": "<NUM>",
"position": 0
},
{
"token": "1234",
"start_offset": 6,
"end_offset": 10,
"type": "<NUM>",
"position": 1
},
{
"token": "1234",
"start_offset": 11,
"end_offset": 15,
"type": "<NUM>",
"position": 2
},
{
"token": "1234",
"start_offset": 16,
"end_offset": 20,
"type": "<NUM>",
"position": 3
},
{
"token": "d123f123g123",
"start_offset": 21,
"end_offset": 33,
"type": "<ALPHANUM>",
"position": 4
}
]
}
Чтобы вернуть документы, которые Field_Name_1
точно соответствуют значению любого из них, вы можете изменить тип данных Field_Name_1
поля на keyword
тип.
Измененное сопоставление индексов будет
{
"mappings": {
"properties": {
"Field_Name_1": {
"type": "keyword"
}
}
}
}
ИЛИ, если вы явно не определили какое-либо сопоставление, вы также можете изменить свой поисковый запрос следующим образом :
{
"query": {
"bool": {
"must": {
"match": {
"Field_Name_1.keyword": "12345-1234-1234-1234-d123f123g123" // note this
}
},
"filter": {
"terms": {
"Field_Name_2": [
1,
2,
3,
4,
5
]
}
}
}
},
"track_total_hits": true
}
При этом будет использоваться keyword
анализатор вместо стандартного анализатора (обратите внимание на поле «.ключевое слово» после Field_Name_1
).
Комментарии:
1. Field_Name_1 был явно определен как текстовое поле, но у меня есть другое поле, которое я определил как текстовое ключевое слово, которое я мог бы использовать вместо Field_Name_1. В противном случае мне пришлось бы переиндексировать данные в новый индекс, который имеет правильный тип для Field_Name_1. Можно ли переиндексировать в новый индекс с тем же именем, не теряя никаких данных? Название индекса имеет значение в моем случае. Есть ли способ получить текущие типы полей, которые я настроил в индексе, чтобы я мог просто изменить те, которые мне нужны при создании новой версии?
2. Если бы я определил свое сопоставление таким образом, как бы я написал ключевое слово и искал его? « ПОМЕСТИТЕ my_index_name/_mapping { «свойства»: { «идентификатор хранилища»: { «тип»: «текст», «поля»: { «ключевое слово»: { «тип»: «ключевое слово», «ignore_above»: 256 } } } } } «
Ответ №2:
Я думаю, что то, что написал ЭСКодер, является ответом на ваш вопрос.
Дополнительно,
«Баллы, рассчитанные для запросов в контексте запроса, представлены в виде чисел с плавающей запятой с одной точностью»
В контексте фильтра баллы не рассчитываются. Контекст фильтра в основном используется для фильтрации структурированных данных, например, установлено ли в поле Field_Name_1 значение «12345-11234-11234-d123f123g123»?
«Часто используемые фильтры будут автоматически кэшироваться Elasticsearch для ускорения производительности».
Если вам требуется точно соответствовать значению Field_Name_1, вы можете использовать фильтры в качестве лучшего варианта.
https://www.elastic.co/guide/en/elasticsearch/reference/7.11/query-filter-context.html
GET Index_Name/_search
{
"query": {
"bool": {
"filter": [
{
"match": {
"Field_Name_1.keyword": "12345-1234-1234-1234-d123f123g123"
}
},
{
"terms": {
"Field_Name_2": [
1,
2,
3,
4,
5
]
}
}
]
}
},
"track_total_hits": true
}