В Elasticsearch, как искать строку в нескольких полях из многоуровневых вложенных объектов - PullRequest
1 голос
/ 27 марта 2019

В Elasticsearch 6 у меня есть данные с вложенными объектами, такими как:

{
    "brands" : 
    [
        {
            "brand_name" : "xyz",
            "products" : 
            [
               {
                   "title" : "test",
                   "mrp" : 100,
                   "sp" : 90,
                   "status" : 1
               },
               {
                   "title" : "test1",
                   "mrp" : 50,
                   "sp" : 45,
                   "status" : 1
                }
            ]
        },
        {
            "brand_name" : "aaa",
            "products" : 
            [
                {
                    "title" : "xyz",
                    "mrp" : 100,
                    "sp" : 90,
                    "status" : 1
                },
                {
                    "title" : "abc",
                    "mrp" : 50,
                    "sp" : 45,
                    "status" : 1
                }
            ]
        }
    ]
}

Я хочу искать либо из поля brand_name, либо из заголовка поля.И я хочу вернуть все результаты в одном и том же inner_hits.

Например: если я введу строку поиска как "xyz", она должна вернуть оба бренда с соответствующим объектом продукта.Если я ввожу строку поиска как «test», она должна возвращать только первый массив брендов с только первым объектом продукта.

Как мне этого добиться.Любые идеи?

Я пытался с вложенным запросом пути, как это:

{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "brands",
            "query": {
              "bool": {
                "should": [
                  {
                    "term": {
                      "brands.brand_name": "xyz"
                    }
                  },
                  {
                    "term": {
                      "brands.brand_name.keyword": "aaa"
                    }
                  },
                  {
                    "nested": {
                      "path": "brands.products",
                      "query": {
                        "bool": {
                          "should": [
                            {
                              "match": {
                                "brands.products.title": "xyz"
                              }
                            }
                          ]
                        }
                      },
                      "inner_hits": {}
                    }
                  }
                ]
              }
            },
            "inner_hits": {}
          }
        }
      ]
    }
  }
}

Но этот запрос возвращается с множественным ответом inner_hits с несколькими объектами массива для каждого бренда и для каждого продукта.

Я хочу, чтобы ответ, как и все названия брендов, которые совпадают со строкой, должен быть указан под одним массивом, а все продукты должны быть перечислены под другим массивом под одинаковыми inner_hits.

1 Ответ

1 голос
/ 27 марта 2019

Поскольку вы хотите, чтобы внутренние совпадения были разными в зависимости от того, где произошло совпадение, т. Е. brands.brand_name или brands.products.title, у вас может быть два запроса, один для названия бренда, а другой - для названия продукта в качестве независимых вложенных запросов. Эти запросы должны быть внутри предложения should запроса bool. Каждый из вложенных запросов должен иметь свой собственный inner_hits, как показано ниже:

{
  "query": {
    "bool": {
      "should": [
        {
          "nested": {
            "path": "brands",
            "inner_hits": {},
            "query": {
              "term": {
                "brands.brand_name.keyword": "test"
              }
            }
          }
        },
        {
          "nested": {
            "path": "brands.products",
            "inner_hits": {},
            "query": {
              "term": {
                "brands.products.title": "test"
              }
            }
          }
        }
      ]
    }
  },
  "_source": false
}
...