Elastic Search - select 来自聚合结果的 DISTINCT 值?

Elastic Search - select DISTINCT value from aggregation result?

在 Elastic Search 中,我有一个名为 Menu 的索引。在 Menu 中有一个 Shop 的数组。像这样。

{
  "menu_id": 1,
  "name": 1,
  "shops": [
    {
      "name": "A",
      "shop_id: "A",
    },
    {
      "name": "B",
      "shop_id: "B",
    }
  ]
}

{
  "menu_id": 2,
  "name": 2,
  "shops": [
    {
      "name": "C",
      "shop_id: "C",
    }
  ]
}

{
  "menu_id": 3,
  "name": 3,
  "shops": [
    {
      "name": "A",
      "shop_id: "A",
    }
  ]
}

{
  "menu_id": 4,
  "name": 4,
  "shops": [
    {
      "name": "A",
      "shop_id: "A",
    },
    {
      "name": "C",
      "shop_id: "C",
    }
  ]
}

根据我的查询,我想搜索 ID 为“A”或“C”的商店。我希望我的结果是这样的。

    {
      "name": "A",
      "shop_id: "A",
    },
    {
      "name": "C",
      "shop_id: "C",
    }

我试过这个查询。

{
  "_source": "shops",
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "shops.id": "A"
          }
        },
        {
          "match": {
            "shops.id": "C"
          }
        }
      ]
    }
  },
  "aggs": {
    "all_shops": {
      "terms": {
        "field": "shops.id.keyword",
        "min_doc_count": 1
      },
      "aggs": {
        "real_shop": {
          "top_hits": {
            "_source": [
              "shops"
            ],
            "size": 1
          }
        }
      }
    }
  }
}

还有这个查询。

{
  "_source": "shops",
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "shops.id": "A"
          }
        },
        {
          "match": {
            "shops.id": "C"
          }
        }
      ]
    }
  },
  "aggs": {
    "messages": {
      "filters": {
        "filters": [
          {
            "match": {
              "shops.id": "A"
            }
          },
          {
            "match": {
              "shops.id": "C"
            }
          }
        ]
      },
      "aggs": {
        "real_shop": {
          "top_hits": {
            "_source": [
              "shops"
            ],
            "size": 1
          }
        }
      }
    }
  }
}

我还有很多“A”、“B”和很多“C”。

我怎样才能只得到一次“A”和一次“C”。

我无法使用索引 Shop 搜索它,因为我想使用 Menu 中的信息来搜索它。

最终查询是“使用商店名称或菜单名称和商店 ID 搜索商店”。

您需要使 shops 成为与查询完全匹配的 nested type, to query on each nested field object. You can use inner_hits 到 return 文档中的一个。如下所示修改您的索引映射

{
  "mappings": {
    "properties": {
      "shops": {
        "type": "nested"
      }
    }
  }
}

搜索查询:

{
  "query": {
    "nested": {
      "path": "shops",
      "query": {
        "terms": {
          "shops.shop_id.keyword": [
            "A",
            "C"
          ]
        }
      },
      "inner_hits": {}
    }
  }
}

搜索结果:

"hits": [
      {
        "_index": "66675093",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "menu_id": 1,
          "name": 1,
          "shops": [
            {
              "name": "A",
              "shop_id": "A"
            },
            {
              "name": "B",
              "shop_id": "B"
            }
          ]
        },
        "inner_hits": {
          "shops": {
            "hits": {
              "total": {
                "value": 1,
                "relation": "eq"
              },
              "max_score": 1.0,
              "hits": [
                {
                  "_index": "66675093",
                  "_type": "_doc",
                  "_id": "1",
                  "_nested": {
                    "field": "shops",
                    "offset": 0
                  },
                  "_score": 1.0,
                  "_source": {
                    "name": "A",            // note this
                    "shop_id": "A"
                  }
                }
              ]
            }
          }
        }
      },
      {
        "_index": "66675093",
        "_type": "_doc",
        "_id": "2",
        "_score": 1.0,
        "_source": {
          "menu_id": 1,
          "name": 1,
          "shops": [
            {
              "name": "C",
              "shop_id": "C"
            }
          ]
        },
        "inner_hits": {
          "shops": {
            "hits": {
              "total": {
                "value": 1,
                "relation": "eq"
              },
              "max_score": 1.0,
              "hits": [
                {
                  "_index": "66675093",
                  "_type": "_doc",
                  "_id": "2",
                  "_nested": {
                    "field": "shops",
                    "offset": 0
                  },
                  "_score": 1.0,
                  "_source": {
                    "name": "C",
                    "shop_id": "C"          // note this
                  }
                }
              ]
            }
          }
        }
      }
    ]

更新 1:

您可以结合使用过滤器聚合和嵌套聚合来实现您的用例。试试下面的查询

{
  "size": 0,
  "aggs": {
    "NAME": {
      "nested": {
        "path": "shops"
      },
      "aggs": {
        "NAME": {
          "filter": {
            "terms": {
              "shops.shop_id.keyword": ["A","C"]
            }
          },
          "aggs": {
            "NAME": {
              "terms": {
                "field": "shops.shop_id.keyword"
              },
              "aggs": {
                "top_sales_hits": {
                  "top_hits": {
                    "size": 1
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

搜索结果将是

"aggregations": {
    "NAME": {
      "doc_count": 6,
      "NAME": {
        "doc_count": 5,
        "NAME": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": "A",
              "doc_count": 3,
              "top_sales_hits": {
                "hits": {
                  "total": {
                    "value": 3,
                    "relation": "eq"
                  },
                  "max_score": 1.0,
                  "hits": [
                    {
                      "_index": "66675093",
                      "_type": "_doc",
                      "_id": "1",
                      "_nested": {
                        "field": "shops",
                        "offset": 0
                      },
                      "_score": 1.0,
                      "_source": {
                        "name": "A",        // note this
                        "shop_id": "A"
                      }
                    }
                  ]
                }
              }
            },
            {
              "key": "C",
              "doc_count": 2,
              "top_sales_hits": {
                "hits": {
                  "total": {
                    "value": 2,
                    "relation": "eq"
                  },
                  "max_score": 1.0,
                  "hits": [
                    {
                      "_index": "66675093",
                      "_type": "_doc",
                      "_id": "2",
                      "_nested": {
                        "field": "shops",
                        "offset": 0
                      },
                      "_score": 1.0,
                      "_source": {
                        "name": "C",      // note this
                        "shop_id": "C"
                      }
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    }
  }