ElasticSearch - фильтрация данных, возвращаемых из вложенного запроса - PullRequest
1 голос
/ 22 апреля 2020

У меня есть набор данных в следующей структуре:

[
    {
        "productId": "ProductId1",
        "customerNumbers": [
            "customer": {
                "name": "Prod1Cust1",
                "totalOrders": 23
            },
            "customer": {
                "name": "Prod2Cust1",
                "totalOrders": 5
            },
            "customer": {
                "name": "Prod3Cust1",
                "totalOrders": 5
            }
        ]
    },
    {
        "productId": "ProductId2",
        "customerNumbers": [
            "customer": {
                "name": "Prod2Cust1",
                "totalOrders": 23
            },
            "customer": {
                "name": "Prod2Cust1",
                "totalOrders": 5
            }
        ]
    }
]

, и мне нужно выбрать все записи, которые имеют префикс of "Prod1, как в поле name (в приведенном примере избегать следует возвращать только первую запись, например ProductId1). Кроме того, при возврате данных мне нужно просто выбрать номер клиента, префикс которого равен Prod1, то есть:

Правильный вывод:

{
        "productId": "ProductId1",
        "customerNumbers": [
            "customer": {
                "name": "Prod1Cust1",
                "totalOrders": 23
            }
        ]
    }

Вместо:

{
        "productId": "ProductId1",
        "customerNumbers": [
            "customer": {
                "name": "Prod1Cust1",
                "totalOrders": 23
            },
            "customer": {
                "name": "Prod2Cust1",
                "totalOrders": 5
            },
            "customer": {
                "name": "Prod3Cust1",
                "totalOrders": 5
            }
        ]
    }

Я могу получить записи, чье Имя * Префикс 1021 * - это «Prod1» с использованием вложенного запроса в сочетании с MatchPhrasePrefixQuery (это возвращает мне результат со всеми номерами клиентов). Как я могу дополнительно отфильтровать данные, чтобы получить номера клиентов с префиксом Name «Prod1».

Следующий мой запрос:

{
    "from": 0,
    "size": 10,
    "sort": [
        {
            "name.keyword": {
                "missing": "_first",
                "order": "asc"
            }
        }
    ],
    "query": {
        "bool": {
            "must": [
                {
                    "bool": {
                        "must": [
                            {
                                "nested": {
                                    "query": {
                                        "bool": {
                                            "must": [
                                                {
                                                    "match": {
                                                        "customerNumbers.name": {
                                                            "query": "Prod1",
                                                            "type": "phrase_prefix"
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    "path": "customerNumbers"
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}

PS: я использую ElasticSearch 5.x с Nest.

1 Ответ

1 голос
/ 22 апреля 2020

Попробуйте использовать inner_hits:

PUT products
{"mappings":{"_doc":{"properties":{"customerNumbers":{"type":"nested"}}}}}

POST products/_doc
{"productId":"ProductId1","customerNumbers":[{"name":"Prod1Cust1","totalOrders":23},{"name":"Prod2Cust1","totalOrders":5},{"name":"Prod3Cust1","totalOrders":5}]}

POST products/_doc
{"productId":"ProductId2","customerNumbers":[{"name":"Prod2Cust1","totalOrders":23},{"name":"Prod2Cust1","totalOrders":5}]}
GET products/_search
{
  "_source": "inner_hits", 
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "must": [
              {
                "nested": {
                  "path": "customerNumbers",
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "match_phrase_prefix": {
                            "customerNumbers.name": {
                              "query": "Prod1"
                            }
                          }
                        }
                      ]
                    }
                  },
                  "inner_hits": {}
                }

              }
            ]
          }
        }
      ]
    }
  }
}

, получив следующие хиты

[
  {
    "_index":"products",
    "_type":"_doc",
    "_id":"tyQGo3EBdiyDG0RsTa0N",
    "_score":0.9808292,
    "_source":{

    },
    "inner_hits":{
      "customerNumbers":{
        "hits":{
          "total":1,
          "max_score":0.9808292,
          "hits":[
            {
              "_index":"products",
              "_type":"_doc",
              "_id":"tyQGo3EBdiyDG0RsTa0N",
              "_nested":{
                "field":"customerNumbers",
                "offset":0
              },
              "_score":0.9808292,
              "_source":{
                "name":"Prod1Cust1",         <-----
                "totalOrders":23
              }
            }
          ]
        }
      }
    }
  }
]
...