ElasticSearch, запрашивающий вложенные объекты, не работает должным образом

Итак, я пытаюсь выполнить поиск по вложенным объектам в ElasticSearch, и я что-то делаю неправильно, так как не получаю результатов.

Я запускаю следующие команды: -

Создать индекс и сопоставления

PUT /demo
{
    "mappings": {
        "person": {
            "properties": {
                "children": {
                    "type": "nested",
                        "properties": {
                            "fullName": {
                                "type": "string"
                            },
                            "gender": {
                                "type": "string",
                                "index": "not_analyzed"
                        }
                    }
                }
            }
        }
    }
}

Добавить документ пользователя

POST /demo/person/1
{
    "children": [{
        "fullName" : "Bob Smith",
        "gender": "M"
    }]
}

Все они выполняются, как и ожидалось. Однако, когда я ищу их, как указано в документация Я не получаю никаких результатов.

Запрос

POST /demo/person/_search
{
    "query": {
        "bool": {
            "must": [{
                "match_all": {}
            },
            {
                "nested": {
                "path": "children",
                "query": {
                    "bool": {
                        "must": [{
                            "match": {
                                "fullName": "Bob Smith"
                            }
                        }]
                    }
                }
                }
            }]
        }
    }
}

Что я делаю неправильно?


person baynezy    schedule 23.07.2016    source источник
comment
вы работаете с полным именем, но это поле сохраняется как children.fullName внутри Lucene. Просто измените на children.fullName :)   -  person Waldemar Neto    schedule 23.07.2016
comment
@WaldemarNeto - спасибо, это была проблема.   -  person baynezy    schedule 24.07.2016


Ответы (1)


Просто чтобы записать ответ, проблема в том, что всем запросам и фильтрам требуется полное имя поля. В приведенном выше примере документ индексируется как:

{
  "children": [
    {
      "fullName" : "Bob Smith",
      "gender": "M"
    }
  ]
}

Чтобы запросить gender, к нему нужно обратиться как children.gender, а чтобы запросить fullName, к нему нужно обратиться как children.fullName.

Все структуры данных JSON эффективно сглаживаются Lucene, что на самом деле является единственной причиной существования типа nested, поэтому:

{
  "children": [
    {
      "fullName" : "Bob Smith",
      "gender": "M"
    },
    {
      "fullName" : "Jane Smith",
      "gender": "F"
    }
  ]
}

становится таким с типом object (по умолчанию):

"children.fullName": [ "Bob Smith", "Jane Smith" ]
"children.gender": [ "M", "F" ]

с типом nested становится:

{
  "children.fullName": [ "Bob Smith" ]
  "children.gender": [ "M" ]
}
{
  "children.fullName": [ "Jane Smith" ]
  "children.gender": [ "F" ]
}

где {} служат границами вложенных документов (буквально они не существуют, но логически они есть).

Таким образом, независимо от того, используете ли вы вложенные документы или нет, вам необходимо указать полный путь к имени поля, даже если последняя часть (например, gender) уникальна для индекса.

Связанный с этим интерес: вы никогда не должны использовать тип nested, если у вас есть только один объект в массиве. Это полезно только тогда, когда вы действительно используете его как массив. Если это не массив, то плоская версия выполняет ту же функцию с меньшими затратами. Если в каких-то документах один, а в каких-то больше одного, то тоже имеет смысл использовать nested.

person pickypg    schedule 23.07.2016