#elasticsearch
#elasticsearch
Вопрос:
Я пытаюсь запросить вложенные свойства с несколькими значениями.
Вот пример, который будет понятнее.
Создайте индекс с вложенным полем
curl -X DELETE "http://localhost:9200/testing_nested_query/"
curl -X POST "http://localhost:9200/testing_nested_query/" -d '{
"mappings": {
"class": {
properties: {
title: {"type": "string"},
"students": {
"type": "nested",
"properties": {
"name": {"type": "string"}
}
}
}
}
}
}'
Добавьте несколько значений
curl -XPUT 'http://localhost:9200/testing_nested_query/class/1' -d '{
"title": "class1",
"students": [{"name": "john"},{"name": "jack"},{"name": "jim"}]
}'
curl -XPUT 'http://localhost:9200/testing_nested_query/class/2' -d '{
"title": "class2",
"students": [{"name": "john"},{"name": "chris"},{"name": "alex"}]
}'
Запрос для всех классов, где находится Джон (2 попадания, как и ожидалось)
curl -XGET 'http://localhost:9200/testing_nested_query/class/_search' -d '{
"query": {
"nested": {
"path":"students",
"query": {
"bool": {
"must": [
{"match": {"students.name": "john"}}
]
}
}
}
}
}'
Запрос классов, в которых учатся Джон и Джек (0 результатов вместо 1)
curl -XGET 'http://localhost:9200/testing_nested_query/class/_search' -d '{
"query": {
"nested": {
"path":"students",
"query": {
"bool": {
"must": [
{"match": {"students.name": "john"}},
{"match": {"students.name": "jack"}}
]
}
}
}
}
}'
Я пробовал использовать match и filter, но я никогда не могу заставить запрос возвращать ожидаемые значения.
Комментарии:
1. Запрос будет работать, просто используя «должен» вместо «must».
2. Нет, с помощью «should» он возвращает 2 попадания вместо одного.
3. Вы правы, я неправильно истолковал вопрос.
Ответ №1:
Это просто нужно немного изменить:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path":"students",
"query": {
"bool": {
"must": [
{"match": {"name": "john"}}
]
}
}
}
},
{
"nested": {
"path":"students",
"query": {
"bool": {
"must": [
{"match": {"name": "jack"}}
]
}
}
}
}
]
}
}
}
Почему?
По сути, во вложенном запросе запрос и фильтр совместно выполняются для одного вложенного документа — в вашем случае для одного имени. Таким образом, ваш запрос поднимет каждый вложенный документ и попытается найти каждый документ, который имеет name
значение john
и jack
одновременно, что невозможно.
Мой запрос пытается найти индексированный документ, в котором один вложенный документ name
равен john
, а другой вложенный документ name
равен jack
. Таким образом, в основном один вложенный запрос пытается полностью сопоставить один вложенный документ.
Чтобы доказать, что я предлагаю, попробуйте это:
Создайте тот же индекс с тем же отображением, что и вы
** Затем проиндексируйте следующие документы **
curl -XPUT 'http://localhost:9200/testing_nested_query/class/1' -d '{
"title": "class1",
"students": [{"name": "john", "age": 4},{"name": "jack", "age": 1},{"name": "jim", "age": 9}]
}'
curl -XPUT 'http://localhost:9200/testing_nested_query/class/2' -d '{
"title": "class1",
"students": [{"name": "john", "age": 5},{"name": "jack", "age": 4},{"name": "jim", "age": 9}]
}'
Теперь выполните следующие запросы:
{
"query": {
"nested": {
"path":"students",
"query": {
"bool": {
"must": [
{"match": {"name": "john"}},
{"match": {"age": 4}}
]
}
}
}
}
}
Согласно вашим ожиданиям, это должно соответствовать двум документам, но на самом деле соответствует только одному. Потому что существует только один вложенный документ, в котором оба значения name
равны john
age
и 4
равны в,,.
Надеюсь, это поможет.
Ответ №2:
Вы также могли бы поступить следующим образом. если вам не нужно снова повторять bool во вложенном блоке , поскольку в этом блоке есть только один , которому нужно соответствовать , вы можете просто выполнить сопоставление терминов без bool
{
"query": {
"bool": {
"must": [{
"nested": {
"path": "students",
"query": {
{
"term": {
"name": "john"
}
}
}
}
}, {
"nested": {
"path": "students",
"query": {
{
"term": {
"name": "jack"
}
}
}
}
}]
}
}
}