首页 > 解决方案 > 弹性:我如何通过字符串键过滤聚合桶

问题描述

我有来自一个提供商的一些数据 - 非常大的结构化 JSON 数据:

  "mappings": {
    "properties": {
      "field_a": { .. },
      "field_b": { .. },
      "field_c": { .. },
      "field_d": {
        "properties": {
          "subfield_a": {...},
          "subfield_b": {...},
          "subfield_c": {...},
          "subfield_d": {...},
          "subfield_e": {
            "properties": {
              "myfield": {
                "type": "keyword"
              },
              "another_a": {...},
              "another_b": {...},
            }
          }
        }
      }
    }
  }

subfield_e 是对象数组,包含许多我感兴趣的字段“myfield”。

我只需要聚合包含一些字符串的字段“myfield”。

所以,我现在这样做是错误的(但逻辑结果):

GET /index/_search
{
  "query": {
    "wildcard": {
      "field_d.subfield_e.myfield": "*string*"
    }
  },
    "aggs": {
      "interest": {
        "terms": {
          "field": "field_d.subfield_e.myfield",
          "size": 10
        }
      }
    },
    "size": 0
}

该查询的问题是,该查询将选择对象数组“esubfield_e”包含带有字符串的对象 myfield 的所有文档,并在这些文档下进行聚合。所以,最后我得到了这些文档下所有“myfields”的结果,而不仅仅是包含string的 myfields 。

我试图在我的主要聚合之后进行 bucket_selector 聚合,但我得到了错误:“buckets_path 必须引用一个数字值或一个单值数字度量聚合,得到:聚合 [_key] 处的 [String]”

我的代码的灵感来自:Filter Elasticsearch Aggregation by Bucket Key Value ,现在看起来:

GET /index/_search
{
  "query": {
    "wildcard": {
      "field_d.subfield_e.myfield": "*string*"
    }
  },
    "aggs": {
      "interest": {
        "terms": {
          "field": "field_d.subfield_e.myfield",
          "size": 10
        }
      },
      "aggs": {
        "buckets": {
          "bucket_selector": {
            "buckets_path": {
              "key": "_key"
            },
            "script": "params.key.contains('string')"
          }
        }
      }
    }
  },
  "size": 0
}

那么,我如何通过它们的字符串键过滤聚合桶(术语 aggs)?

标签: elasticsearchfilteraggregation

解决方案


我通过将 subfield_e 切换到嵌套对象而不是未定义数组来解决它,并将所有数据重新导入到这个新映射中。

当前映射如下所示:

  "mappings": {
    "properties": {
      "field_a": { .. },
      "field_b": { .. },
      "field_c": { .. },
      "field_d": {
        "properties": {
          "subfield_a": {...},
          "subfield_b": {...},
          "subfield_c": {...},
          "subfield_d": {...},
          "subfield_e": {
            "type": "nested"    <======= This line added
            "properties": {
              "myfield": {
                "type": "keyword"
              },
              "another_a": {...},
              "another_b": {...},
            }
          }
        }
      }
    }
  }

最后的工作查询是:

GET /index/_search
{
  "query": {
    "nested": {
      "path": "field_d.subfield_e",
      "query": {
        "wildcard": {
          "field_d.subfield_e.myfield": {
            "value": "*string*"
          }
        }
      }
    }
  },
  "aggs": {
    "agg": {
      "nested": {
        "path": "field_d.subfield_e"
      },
      "aggs": {
        "inner": {
          "filter": {
            "wildcard": {
              "field_d.subfield_e.myfield": "*string*"
            }
          }, "aggs": {
            "interest": {
              "terms": {
                "field": "field_d.subfield_e.myfield",
                "size": 10
              }
            }
          }
        }
      }
    }
  },
  "size": 0
}

在我的情况下,此查询的速度比在术语聚合中使用包含/排除要好得多。


推荐阅读