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

时间:2014-09-03 16:24:15

标签: elasticsearch aggregation cardinality

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

doc field1 field2

  1. AAA:BBB
  2. AAA:CCC
  3. PPP:QQQ
  4. PPP:QQQ
  5. XXX:YYY
  6. XXX:YYY
  7. MMM:NNN
  8. 文档的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 个答案:

答案 0 :(得分:2)

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

我在这里有一个类似的例子。

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

现在,如果我想找到至少一次服用阿司匹林的患者人数,那么查询可能是:

{
  "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" } }
          }
  }}}}
}

示例结果:

{
  "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。

希望这对您的问题有所帮助。

答案 1 :(得分:0)

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

一种简单的方法是仅过滤AAA'最高聚合中的记录:

minorticks