2016-10-04 56 views
1

多AGGS我与ES一个小白,我不知道如何解决这个简单的场景:与ElasticSearch

 
dataType value 

    1 A 
    1 A 
    1 B 
    2 B 
    3 A 
    3 A 
    4 A 
    4 B 

我需要知道有多少数据类型只有“A”值,有多少只'B'值,以及两者都有。在这个例子中预期的结果将是:

Only A = 1 (dataType 3) 
Only B = 1 (dataType 2) 
Both = 2 (dataTypes 1 and 4) 

你能帮助我吗?谢谢。

ChintanShah25嗨,非常感谢您的快速回复。我想你已经制定,但似乎不能正常工作代码:

"Aggregations": { 
         "Datatypes": { 
             "Value": { 
             "Both": 0, 
                "Onlya": 1, 
                "OnlyB": 1 
            } 
        } 
    } 

如果我删除“reduce_script”我可以调试,获得:

 

    "Aggregations": { 
     "Datatypes": { 
     "Value": [ 
                    [ 
                        [ 
                            "1" 
                        ], 
                        [] 
                    ], 
                    [ 
                        [] 
                        [] 
                    ], 
                    [ 
                        [ 
                            "1" 
                        ], 
                        [ 
                            "1", 
                            "2" 
                        ] 
                    ], 
                    [ 
                        [ 
                            "4" 
                        ], 
                        [] 
                    ], 
                    [ 
                        [ 
                            "3" 
                        ], 
                        [ 
                            "4" 
                        ] 
                    ] 
                ] 
            } 
        } 

数据类型是正确的分组,但似乎他们是分成不同的桶或锐器,最后一步“reduce_script”失败。

文档“脚本度量标准”很差,虽然测试没有达到预期的结果。

问候。

回答

2

我想这很棘手,可以通过scripted metric aggregation完成。我创建了一个测试索引并插入了您提供的示例数据。下面的查询让你想

{ 
    "query": { 
    "match_all": {} 
    }, 
    "aggs": { 
    "Datatypes": { 
     "scripted_metric": { 
     "init_script": "_agg['onlya'] = [];_agg['onlyb'] = [];", 
     "map_script": "if (doc['value'].value == \"A\") 
         { _agg.onlya.add(doc['datatype'].value) }; 
         if (doc['value'].value == \"B\") 
         { _agg.onlyb.add(doc['datatype'].value) };", 
     "combine_script": "onlya = _agg['onlya'].unique(); 
          onlyb = _agg['onlyb'].unique(); 
          return[onlya, onlyb]", 
     "reduce_script": "both_bucket=[];a_bucket=[];b_bucket=[]; 
          for(a in _aggs) 
          {both_bucket=a[0].intersect(a[1]); 
          a_bucket=a[0]-a[1]; 
          b_bucket=a[1]-a[0]}; 
          return ['Both' : both_bucket.size(), 
            'OnlyA' : a_bucket.size(), 
            'OnlyB' : b_bucket.size()];" 
     } 
    } 
    }, 
    "size": 0 
} 

结果这是输出我得到

"aggregations": { 
     "Datatypes": { 
     "value": { 
      "Both": 2, 
      "OnlyA": 1, 
      "OnlyB": 1 
     } 
     } 
    } 

您将需要enable dynamic scripting这个工作或者把这些脚本scripts folder

期间init_script,我声明了两个变量,它们将保存数据类型的值。

map_script经过每一个文件,并增加了数据类型为分析:定冠词如果值是“A”或onlyb。你可以用别的替代第二,如果你确信你要么有A或B

combine_script转换列表中唯一值,以便[1,1,3,3,4]成为[1,3,4]

reduce_script会从所有的碎片结果。 交叉口会给你两个数据类型值和减法会给你只有部分。 size()为您提供列表的长度。移除size方法以获得匹配的数据类型值。

请通过documentation找到更多关于如何聚集所有这些工作不同阶段

0

我终于得到它的工作,因为我想要的。非常感谢您的帮助。

"aggs": { 
    "Datatypes": { 
     "scripted_metric": { 
     "init_script": "_agg['onlya'] = [];_agg['onlyb'] = [];", 
     "map_script": "valueAdd=doc['datatype'].value; if (doc['value'].value == \"a\") { _agg['onlya'].add(valueAdd) }; if (doc['value'].value == \"b\") { _agg['onlyb'].add(valueAdd) };", 
     "combine_script": "onlya = _agg['onlya'].unique();       onlyb = _agg['onlyb'].unique();       return[onlya, onlyb]", 
     "reduce_script": "a_bucket=[];b_bucket=[];for(a in _aggs){ a_bucket+=a[0]; b_bucket+=a[1];}; return ['Both' : a_bucket.intersect(b_bucket).size(), 'OnlyA' : (a_bucket-b_bucket).size(), 'OnlyB' : (b_bucket-a_bucket).size()];" 

     } 
    } 
    }