绊脚石乃是进身之阶。

请教一个搜索结果的汇总统计的问题

Elasticsearch | 作者 wen | 发布于2018年06月14日 | 阅读数:1546

用java(web)连接ES进行查询,在某个索引中有用户名和标签列表两个字段,
如下记录:
"name":"路人甲" , "tags": "A, B, "
"name":"路人乙 , "tags": "A, C"
"name":"路人丙" , "tags": "A"
"name":"路人丁" , "tags": "B, C"
A,B,C表示标签,目前tags是一个字符串(以后可能是一个数组,例如[{"tag":"A", "date":"20180101"}, {"tag":"A", "date":"20180101"} ...])

例如我在搜索结果中,想统计每个标签出现的次数,比如搜索A,结果得到 A:3, B:2, C:1

目前我的做法是,使用scrollID的方式查询A,然后遍历结果,根据每条自己统计出现的次数
另外还有一个数据导出的功能(将es搜索结果导出到文件,提供下载),用的也是类似的套路(也用scroll,不统计而是写文件)

遇到的问题是:
1、效率不高,在3个虚拟机,200w记录的测试环境,10w的结果集的统计,大概要10分钟左右吧。
2、担心多个统计任务并发,会对java程序和es造成压力;scroll的原来是ES做了docID的快照,快照也是要占空间的,不知道scroll有没有个数限制?
3、扩展性不好(所以tag字段准备改进为json数组)

想请教一下:
ES的aggres能否解决我这个问题?(我知道sql中类似的问题,一种方法是把字段分割转换为行然后groupby)
如果还是得查出来在程序中统计,这种场景有没有更好的搜索方式?

谢谢!
已邀请:

wen

赞同来自: haoxuexiong

经过一番研究,找到了一个方法,首先tag字段,不能用字符串(或者说我没找到字符串分割方法),而是用json标签,例如:
{"tag" : [{"name":"A"}, {"name":"B"} ...]}
 
这样在aggres里面,按tag.name分桶就可以了,其实是个非常简单的问题
 
  "aggs": {
    "tag_count": {
      "terms": {
        "field":  "tag.name.keyword",
      }
    }
  }
 
 
 
 

haoxuexiong

赞同来自:

aggres只能对字段进行聚合吧?比如你对tags字段做聚合,那么ES会认为tags=“A,B”和tags=“A,B,C”是不同项,统计出来的结果类似这样["A,B",1],["A,B,C":1]  key是统计项,value是统计到的key的所有的次数。
我理解是这样的哈,如果答错了轻拍

dingzhang

赞同来自:

先聚合,再统计数量,不需要去遍历结果

要回复问题请先登录注册