Elasticsearch - multi_match не работает с вложенными полями

У меня есть записи, которые могут иметь несколько переводов для одного текстового поля, например:

{
  "type": "movie",
  "title": {
    "en": "Dark Knight",
    "de": "Der dunkle Ritter"
  }
}

Для представления этих записей я создал следующий индекс:

{
  "mappings": {
    "_doc": {
      "properties": {
        "type": {
          "type": "text",
          "analyzer": "english"
        },
        "title": {
          "type": "nested",
          "properties": {
            "de": {
              "type": "text",
              "analyzer": "german"
            },
            "en": {
              "type": "text",
              "analyzer": "english"
            }
          }
        }
      }
    }
  }
}

Но когда я пытаюсь использовать multi_map запрос, он не возвращает ожидаемого результата. Этот запрос находит запись (поиск по полю type верхнего уровня):

{
    "query": { 
        "multi_match" : {
            "query" : "movie"
        }
    }
}

Но в этом запросе нет (поиск по вложенному полю title.en):

{
  "query": {
    "multi_match" : {
      "query": "dark"
    }
  }
}

Это удивительно, поскольку, если я получаю векторы терминов для поля title.en, кажется, что запись была правильно проиндексирована:

GET /test_with_lang/_doc/1/_termvectors?pretty=true&fields=*

{
    "_index": "test_with_lang",
    "_type": "_doc",
    "_id": "1",
    "_version": 1,
    "found": true,
    "took": 1,
    "term_vectors": {
        "title.en": {
            "field_statistics": {
                "sum_doc_freq": 2,
                "doc_count": 1,
                "sum_ttf": 2
            },
            "terms": {
                "dark": {
                    "term_freq": 1,
                    "tokens": [
                        {
                            "position": 0,
                            "start_offset": 0,
                            "end_offset": 4
                        }
                    ]
                },
                "knight": {
                    "term_freq": 1,
                    "tokens": [
                        {
                            "position": 1,
                            "start_offset": 5,
                            "end_offset": 11
                        }
                    ]
                }
            }
        }
    }
}

Также кажется, что запрос использует правильные поля и должен соответствовать одному из токенов:

Request:
GET /test_with_lang/_doc/1/_explain
{
  "query": {
    "multi_match" : {
      "query": "dark"
    }
  }
}


Reply:
{
    "_index": "test_with_lang",
    "_type": "_doc",
    "_id": "1",
    "matched": false,
    "explanation": {
        "value": 0.0,
        "description": "Failure to meet condition(s) of required/prohibited clause(s)",
        "details": [
            {
                "value": 0.0,
                "description": "no match on required clause ((type:dark | title.en:dark | title.de:dark))",
                "details": [
                    {
                        "value": 0.0,
                        "description": "No matching clause",
                        "details": []
                    }
                ]
            },
        ...
                ]
            }
        ]
    }
}

Обратите внимание, что он ищет токен dark в поле title.en (no match on required clause ((type:dark | title.en:dark | title.de:dark))).

Я использую Elasticsearch 6.2.1

Вроде бы запрос должен работать. Я что-то упускаю?


person Ivan Mushketyk    schedule 16.02.2018    source источник


Ответы (1)


Вложенные поля требуют специальных вложенных запросов:

"query": {
  "nested": {
    "path": "title",
    "query": {
      "multi_match": {
        "query": "dark"
      }
    }
  }
}

Но сомневаюсь, что в вашем случае нужны вложенные поля. Просто используйте обычный тип объекта для поля title, чтобы иметь возможность находить по всем полям документа с помощью простого multi_match запроса.

person briarheart    schedule 16.02.2018
comment
Есть ли способ установить разные текстовые анализаторы для разных подполей без использования вложенных полей? Поскольку разные поля будут на разных языках, ES придется применять разные алгоритмы обработки текста. - person Ivan Mushketyk; 27.02.2018
comment
@IvanMushketyk Только не используйте тип nested. Сопоставление поля title должно выглядеть так: "title": {"properties": {"de": {"type": "text", "analyzer": "german"}, "en": {"type": "text", "analyzer": "english"}}}. В этом случае тип поля title - object, что позволяет использовать следующий multi_match запрос: "multi_match": {"query": "Dunkle","fields": ["title.*"]}. - person briarheart; 28.02.2018