[Elastcisearch] 通过聚合完成热度分数计算

一、概要

分配给我的需求中,有一个需求是基于行为索引完成热度排行,我的想法就是通过聚合配合脚本语言完成该需求。

热度排行:一篇文档被收藏获得2分,被浏览获得1分,需要再行为表中聚合出得分最多的10篇文档,完成热度排行!

此处我们也看出需要对行为表进行聚合,字段不同的值 得到不同的分数,并且最后累加,获取总分,得出热度排行!

下面用简单示例解读如何完成这种需求的聚合

二、前置工作

a、创建行为索引

behavior代表行为码值(比如 1代表浏览 2代表收藏)

data_id代表行为对应的原文档的唯一标识

PUT /test_behavior_index
    {
        "mappings": {
			"properties": {
				"behavior": {
					"type": "byte"
				},
				"data_id": {
					"type": "keyword"
				}
			}
		}
    }

b、创建原文索引

就是一个测试的索引,没有特殊意义

为的就是有数据供上面的行为索引进行关联操作(收藏,浏览等)

PUT /test_index
{
	"mappings": {
		"properties": {
			"title": {
				"type": "text"
			},
			"content": {
				"type": "text"
			}
		}
	}
}

c、插入测试数据

插入两个文档


POST /test_index/_doc/1
{
	"title": "库里传",
	"content": "历史上最伟大的球员之一......"
}

POST /test_index/_doc/2
{
	"title": "追梦格林为人称赞的防守策应",
	"content": "一个小个子为什么可以打5号位,又为什么可以串联球队....."
}

为两个文档插入行为数据

(id为1的文档:被浏览2次收藏2次)

(id为2的文档:被浏览1次)

# 此处可以用bluk批量插入
# 文档1 也就是库里传被收藏2次浏览2次
# 文档2 也就是追梦被浏览1次
POST /test_index/_doc/_bulk
{"index":{"_id":1}}
{"behavior":1,"data_id":"1"}
{"index":{"_id":2}}
{"behavior":1,"data_id":"1"}
{"index":{"_id":3}}
{"behavior":2,"data_id":"1"}
{"index":{"_id":4}}
{"behavior":2,"data_id":"1"}
{"index":{"_id":5}}
{"behavior":1,"data_id":"2"}





三、脚本聚合解决

解读该DSL:

首先通过一次termsAgg对data_id进行buckets聚合分组,旨在不同data_id的文档放入一个桶中!

第二次聚合为sumAgg的数字度量聚合,旨在将所有data_id的相同的文档的行为所得分数分累加

脚本解读:

其实非常简单的脚本。

如果我们的行为behavior字段为1(也就是浏览),那么就得到1分

如果我们行为behavior字段为2(收藏),那么就得到2分

但是值得注意的是,我们最好把参数放进params里,这样维护起来也相对简单,并且不会出现魔法值。

而且painess脚本不允许直接返回一个单体数字!所以更应该放进params中!

POST /test_behavior_index/_search
{
	"query": {
		"match_all": {}
	},
	"size": 0,
	"aggs": {
		"terms_agg": {
			"terms": {
				"field": "data_id",
				"order": {
					"sum_agg": "desc"
				}
			},
			"aggs": {
				"sum_agg": {
					"sum": {
						"script": {
							"source": "if(doc['behavior'].value == 1){ return params['viewScore']} else if(doc['behavior'].value == 2) { return params['faviortScore']}",
							"params": {
								"viewScore": 1,
								"faviortScore": 2
							}
						}
					}
				}
			}
		}
	}
}

结果:

第一个文档被收藏2次,浏览两次获得 6分

第二个文档被浏览1次,获得1分

结果正确!

{
    "took":9,
    "timed_out":false,
    "_shards":{
        "total":1,
        "successful":1,
        "skipped":0,
        "failed":0
    },
    "hits":{
        "total":{
            "value":6,
            "relation":"eq"
        },
        "max_score":null,
        "hits":[

        ]
    },
    "aggregations":{
        "terms_agg":{
            "doc_count_error_upper_bound":0,
            "sum_other_doc_count":0,
            "buckets":[
                {
                    "key":"1",
                    "doc_count":4,
                    "sum_agg":{
                        "value":6
                    }
                },
                {
                    "key":"2",
                    "doc_count":1,
                    "sum_agg":{
                        "value":1
                    }
                }
            ]
        }
    }
}

四、总结

相对比较简单,总体来说是一个桶聚合内部放入数字聚合,配合脚本对数字聚合得字段进行一个乘积控制!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值