首页 文章

Elasticsearch术语或基数聚合 - 按不同值的数量排序

提问于
浏览
1

朋友们,

我正在做一些分析,以找出数百万个文档中的唯一对 . 模拟示例如下所示:

doc field1 field2

  • AAA:BBB

  • AAA:CCC

  • PPP:QQQ

  • PPP:QQQ

  • XXX:YYY

  • XXX:YYY

  • MMM:NNN

90%的文档包含一个唯一的对,如上面的文档3,4,5,6和7所示,我对我的聚合结果不感兴趣 . 我有兴趣汇总文档1和2 .

条款聚合查询:

"aggs": {
        "f1": {
            "terms": {
                "field": "FIELD1",
                "min_doc_count": 2
              },
              "aggs": {
                "f2": {
                      "terms": {
                    "field": "FIELD2"
                      }
                }
              }
        }
    }

术语聚合结果

"aggregations": {
         "f1": {
               "buckets": [
                 {
                    "key": "PPP",
                    "doc_count": 2,
                    "f2": {
                        "buckets": [
                              {
                               "key": "QQQ",
                            "doc_count": 2
                              }
                         ]
                    }
                  },
                  {
                    "key": "XXX",
                    "doc_count": 2,
                    "f2": {
                        "buckets": [
                              {
                               "key": "YYY",
                            "doc_count": 2
                              }
                         ]
                    }
                  },
                  {
                    "key": "AAA",
                    "doc_count": 2,
                    "f2": {
                        "buckets": [
                              {
                                   "key": "BBB",
                                "doc_count": 1
                              },
                              {
                               "key": "CCC",
                               "doc_count": 1
                              }
                         ]
                    }
                  }
            ]
         }
    }

我只对密钥 AAA 感兴趣的是聚合结果 . 筛选包含不同对的聚合结果的最佳方法是什么?

我尝试使用基数聚合,这会导致unque值计数 . 但是我无法从聚合结果中筛选出我不感兴趣的内容 .

基数聚合查询

"aggs": {
        "f1": {
            "terms": {
                "field": "FIELD1",
                "min_doc_count": 2
              },
            "aggs": {
                "f2": {
                      "cardinality": {
                        "field": "FIELD2"
                      }
                }
              }
        }
    }

基数聚合结果

"aggregations": {
        "f1": {
               "buckets": [
                 {
                    "key": "PPP",
                    "doc_count": 2,
                    "f2": {
                          "value" : 1
                    }
                  },
                  {
                    "key": "XXX",
                    "doc_count": 2,
                    "f2": {
                          "value" : 1
                    }
                  },
                  {
                    "key": "AAA",
                    "doc_count": 2,
                    "f2": {
                          "value" : 2
                    }
                  }
            ]
         }
    }

至少如果我可以按基数值排序,这将有助于我找到一些解决方法 . 请帮助我这方面 .

P.S:写一个spark / mapreduce程序来发布过程/过滤聚合结果不是这个问题的预期解决方案 .

2 回答

  • 2

    我建议使用过滤器查询和聚合,因为您只对field1 = AAA感兴趣 .

    我这里有一个类似的例子 .

    例如,我有我医院所有患者的索引 . 我将他们的药物使用存储在嵌套对象DRUG中 . 每位患者可以服用不同的药物,每种药物可以多次服用一种药物 .

    现在,如果我想找到至少一次服用 aspirin 的患者数量,那么查询可能是:

    {
      "size": 0,
      "_source": false,
      "query": {
        "filtered": {
          "query": {
            "match_all": {}
          },
          "filter": {
            "nested": {
              "path": "DRUG",
              "filter": {
                "bool": {
                  "must": [{ "term": { "DRUG.NAME": "aspirin" } }]
      }}}}}},
      "aggs": {
        "DRUG_FACETS": {
          "nested": {
            "path": "DRUG"
          },
          "aggs": {
            "DRUG_NAME_FACETS": {
              "terms": { "field": "DRUG.NAME", "size": 0 },
              "aggs": {
                "DISTINCT": { "cardinality": { "field": "DRUG.PATIENT" } }
              }
      }}}}
    }
    

    Sample result:

    {
      "took": 6,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 6,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "DRUG_FACETS": {
          "doc_count": 11,
          "DRUG_NAME_FACETS": {
            "buckets": [
              {
                "key": "aspirin",
                "doc_count": 6,
                "DISTINCT": {
                  "value": 6
                }
              },
              {
                "key": "vitamin-b",
                "doc_count": 3,
                "DISTINCT": {
                  "value": 2
                }
              },
              {
                "key": "vitamin-c",
                "doc_count": 2,
                "DISTINCT": {
                  "value": 2
                }
              }
            ]
          }
        }
      }
    }
    

    水桶中的第一个是阿司匹林 . 但是你可以看到其他2名患者在服用阿司匹林时也服用了维生素b .

    如果您将DRUG.NAME的字段值更改为另一个药物名称,例如“维生素-b”,我想您会在桶的第一个位置获得维生素b .

    希望这对您的问题很有帮助 .

  • 0

    有点晚了,希望对别人有所帮助 .

    一种简单的方法是在顶部聚合中仅过滤“AAA”记录:

    {
      "size": 0,
      "aggregations": {
        "filterAAA": {
          "filter": {
            "term": {
              "FIELD1": "AAA"
            }
          },
          "aggregations": {
            "f1": {
              "terms": {
                "field": "FIELD1",
                "min_doc_count": 2
              },
              "aggregations": {
                "f2": {
                  "terms": {
                    "field": "FIELD2"
                  }
                }
              }
            }
          }
        }
      }
    }
    

相关问题