如何根据另一个聚合的具体值聚合elasticsearch结果?

问题描述 投票:0回答:1

我无法根据之前聚合的结果正确过滤数据。

我的 Elasticsearch 数据有以下映射:

"properties": {
  "day": {
    "type": "date",
    "format": "yyyy-MM-dd"
  },
  "persons": {
    "type": "nested",
    "properties": {
      "id": {
        "type": "integer"
      },
      "name": {
        "type": "text",
        "analyzer": "final",
        "fields": {
          "raw": {
            "type": "keyword",
            "index": true
          }
        }
      },
      "role": {
        "type": "keyword"
      },
    }
  }
}

假设我在其中保存以下数据:

{
  "workshops": [
    {
      "day": "2023-12-01",
      "persons": [
        {
          "name": "Max",
          "role": "infrastructure"
        },
        {
          "name": "Sam",
          "role": "infrastructure"
        },
        {
          "name": "Sam",
          "role": "database"
        },
        {
          "name": "Peter",
          "role": "network"
        },
        {
          "name": "Peter",
          "role": "infrastructure"
        }
      ]
    },
    {
      "day": "2023-12-02",
      "persons": [
        {
          "name": "George",
          "role": "infrastructure"
        },
        {
          "name": "Michael",
          "role": "database"
        },
        {
          "name": "Michael",
          "role": "network"
        },
        {
          "name": "Sam",
          "role": "administration"
        }
      ]
    }
  ]
}

我有以下聚合:

{
  "aggregations": [
    {
      "persons": {
        "nested": {
          "path": "persons"
        },
        "aggs": {
          "nestedData": {
            "terms": {
              "field": "persons.name.raw"
            },
            "aggs": {
              "name": {
                "terms": {
                  "field": "persons.name.raw"
                }
              }
            }
          }
        }
      }
    },
    {
      "persons_role_de_de": {
        "nested": {
          "path": "persons"
        },
        "aggs": {
          "nestedData": {
            "terms": {
              "field": "persons.role"
            },
            "aggs": {
              "name": {
                "terms": {
                  "field": "persons.role"
                }
              }
            }
          }
        }
      }
    }
  ]
}

当我只进行简单查询(match_all)并过滤掉任何内容时,我得到了预期的结果:

  • 最大(1)

  • 乔治 (1)

  • 山姆(3)

  • 彼得(2)

  • 迈克尔 (2)

  • 基础设施 (4)

  • 数据库(2)

  • 网络(2)

  • 管理(1)

我现在想要得到的是以下内容。首先我过滤“Sam”:

{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "persons",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "persons.name": "sam"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

并获得以下角色聚合,基本相同,因为“Sam”是两个研讨会的一部分:

  • 基础设施(4)
  • 数据库(2)
  • 网络(2)
  • 管理(1)

但我真正想要得到的是以下内容:

  • 基础设施(1)
  • 数据库(1)
  • 管理(1)

因为这是“Sam”的角色,所以我对其他人的其他角色不感兴趣。我的目标是获得唯一一个“Sam”具有“数据库”角色的研讨会。但我没有得到正确的聚合以及选择角色后必须遵循的查询。

elasticsearch elasticsearch-aggregation elasticsearch-dsl
1个回答
0
投票

您编写的查询聚合了所有文档中的所有角色,而不仅仅是名为“Sam”的人。要获取专门针对“Sam”的角色,您需要使用过滤器聚合在嵌套聚合中。以下是修改查询的方法:

在您的情况下,查询正确过滤了名称为“Sam”的文档,但聚合应用于与查询匹配的所有文档,而不仅仅是名称为“Sam”的嵌套文档。

这是因为查询和聚合的范围是 嵌套时不同。查询对顶级文档进行操作, 而聚合则对嵌套文档进行操作。

在下面我提供的修改后的查询中,“sam_filter”过滤器聚合确保只有名称为“Sam”的嵌套文档包含在“nestedData”术语聚合中。这将为您提供专门针对“Sam”的每个角色的计数。

注意:我测试时使用的是ES v8,根据需要修改查询。

#the mapping (workshops nested type added)
PUT sam2
{
  "mappings": {
    "properties": {
      "workshops": {
      "type": "nested",
      "properties": {
        
          "day": {
            "type": "date",
            "format": "yyyy-MM-dd"
          },
          "persons": {
            "type": "nested",
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "text",
                "fields": {
                  "raw": {
                    "type": "keyword",
                    "index": true
                  }
                }
              },
              "role": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
  }
}

#sample document
PUT sam2/_doc/1
{
  "workshops": [
    {
      "day": "2023-12-01",
      "persons": [
        {
          "name": "Max",
          "role": "infrastructure"
        },
        {
          "name": "Sam",
          "role": "infrastructure"
        },
        {
          "name": "Sam",
          "role": "database"
        },
        {
          "name": "Peter",
          "role": "network"
        },
        {
          "name": "Peter",
          "role": "infrastructure"
        }
      ]
    },
    {
      "day": "2023-12-02",
      "persons": [
        {
          "name": "George",
          "role": "infrastructure"
        },
        {
          "name": "Michael",
          "role": "database"
        },
        {
          "name": "Michael",
          "role": "network"
        },
        {
          "name": "Sam",
          "role": "administration"
        }
      ]
    }
  ]
}

#all results
GET sam2/_search
{
  "size": 0,
  "query": {
    "nested": {
      "path": "workshops.persons",
      "query": {
        "term": {
          "workshops.persons.name.raw": "Sam"
        }
      }
    }
  },
  "aggs": {
    "persons": {
      "nested": {
        "path": "workshops.persons"
      },
      "aggs": {
        "nestedData": {
          "terms": {
            "field": "workshops.persons.name.raw"
          }
        }
      }
    },
    "persons_role_de_de": {
      "nested": {
        "path": "workshops.persons"
      },
      "aggs": {
        "nestedData": {
          "terms": {
            "field": "workshops.persons.role"
          }
        }
      }
    }
  }
}

#filter 添加到嵌套聚合内部。 获取 sam2/_search { “大小”:0, “阿格斯”:{ “人”:{ “嵌套”:{ "path": "workshops.persons" }, “阿格斯”:{ “萨姆过滤器”:{ “筛选”: { “学期”: { "workshops.persons.name.raw": "山姆" } }, “阿格斯”:{ “嵌套数据”:{ “条款”:{ "field": "workshops.persons.role" } } } } } } } }

© www.soinside.com 2019 - 2024. All rights reserved.