3

朋友们,

我正在做一些分析,以从数以亿计的文档中找到唯一的对。模拟示例如下所示:

文档字段 1 字段 2

  1. AAA : BBB
  2. AAA : CCC
  3. 购买力平价:QQ
  4. 购买力平价:QQ
  5. XXX : 年年
  6. XXX : 年年
  7. 嗯:NNN

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

术语聚合查询:


    “聚合”:{
        “f1”:{
            “条款”:{
                “字段”:“字段1”,
                “min_doc_count”:2
              },
              “聚合”:{
                “f2”:{
                      “条款”:{
                    “字段”:“字段 2”
                      }
                }
              }
        }
    }

术语聚合结果


    “聚合”:{
         “f1”:{
               “桶”:[
                 {
                    “关键”:“PPP”,
                    “文档计数”:2,
                    “f2”:{
                        “桶”:[
                              {
                               "key": "QQQ",
                            “文档计数”:2
                              }
                         ]
                    }
                  },
                  {
                    “关键”:“XXX”,
                    “文档计数”:2,
                    “f2”:{
                        “桶”:[
                              {
                               "key": "YYY",
                            “文档计数”:2
                              }
                         ]
                    }
                  },
                  {
                    “钥匙”:“AAA”,
                    “文档计数”:2,
                    “f2”:{
                        “桶”:[
                              {
                                   “关键”:“BBB”,
                                “文档计数”:1
                              },
                              {
                               “关键”:“CCC”,
                               “文档计数”:1
                              }
                         ]
                    }
                  }
            ]
         }
    }

我只对聚合结果中的密钥AAA感兴趣。过滤包含不同对的聚合结果的最佳方法是什么?

我尝试了基数聚合,这导致了 unque 值计数。但是,我无法从聚合结果中过滤掉我不感兴趣的内容。

基数聚合查询


    “聚合”:{
        “f1”:{
            “条款”:{
                “字段”:“字段1”,
                “min_doc_count”:2
              },
            “聚合”:{
                “f2”:{
                      “基数”:{
                        “字段”:“字段 2”
                      }
                }
              }
        }
    }

基数聚合结果


    “聚合”:{
        “f1”:{
               “桶”:[
                 {
                    “关键”:“PPP”,
                    “文档计数”:2,
                    “f2”:{
                          “价值”:1
                    }
                  },
                  {
                    “关键”:“XXX”,
                    “文档计数”:2,
                    “f2”:{
                          “价值”:1
                    }
                  },
                  {
                    “钥匙”:“AAA”,
                    “文档计数”:2,
                    “f2”:{
                          “价值”:2
                    }
                  }
            ]
         }
    }

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

PS:编写 spark/mapreduce 程序来后处理/过滤聚合结果不是此问题的预期解决方案。

4

2 回答 2

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 的字段值更改为另一个药物名称,例如“vitamin-b”,我想您会在存储桶的第一个位置获得维生素 b。

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

于 2014-10-26T06:54:21.647 回答
0

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

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

{
  "size": 0,
  "aggregations": {
    "filterAAA": {
      "filter": {
        "term": {
          "FIELD1": "AAA"
        }
      },
      "aggregations": {
        "f1": {
          "terms": {
            "field": "FIELD1",
            "min_doc_count": 2
          },
          "aggregations": {
            "f2": {
              "terms": {
                "field": "FIELD2"
              }
            }
          }
        }
      }
    }
  }
}
于 2017-08-23T11:33:54.850 回答