ElasticSearch聚合分析

聚合用于分析查询结果集的统计指标,我们以观看日志分析为例,介绍各种常用的ElasticSearch聚合操作。

目录:

  • 查询用户观看视频数和观看时长
  • 聚合分页器
  • 查询视频uv
    • 单个视频uv
    • 批量查询视频uv
  • Having查询
    • 根据 count 进行过滤
    • 根据其它指标进行过滤

首先展示一下我们要分析的文档结构:

{"video_id": 1289643545120062253, // 视频id"video_uid": 3931482202390368051, // 视频发布者id"uid": 47381776787453866, // 观看用户id"time": 1533891263224, // 时间发生时间"watch_duration": 30 // 观看时长
}

每个文档记录了一个观看事件,我们通过聚合分析用户的观看行为。

ElasticSearch引入了两个相关概念:

  • 桶(Buckets): 满足特定条件的文档的集合
  • 指标(Metrics): 桶中文档的统计值,如特定字段的平均值

查询用户观看视频数和观看时长

首先用sql语句描述这个查询:

SELECT uid, count(*) as view_count
FROM view_log
WHERE time >= #{since} AND time <= #{to} 
GROUP BY uid;

ES 查询:

GET /view_log/_search
{"size" : 0,"query": {"range": {"time": {"gte": 0, // since"lte": 0 // to}}},"aggs": {"agg": { // agg为聚合的名称"terms": { // 聚合的条件为 uid 相同"field": "uid"}}}
}

response:

{"took": 10,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 100000,"max_score": 0,"hits": []},"aggregations": {"agg": {"buckets": [{"key": 21836334489858688,"doc_count": 4026},{"key": 31489302390368051,"doc_count": 2717}]}
}

result.aggregations.agg.buckets列表中包含了查询的结果。

因为我们按照terms:uid进行聚合,每个bucket为uid相同的文档集合,key字段即为uid。

doc_count 字段表明bucket中文档的数目即sql语句中的count(*) as view_count

我们可以为查询添加额外的统计指标, sql描述:

SELECT uid, count(*) as view_count, avg(watch_duration) as avg_duration 
FROM view_log
WHERE time >= #{since} AND time <= #{to} 
GROUP BY uid;

ES 查询:

GET /view_log/_search
{"size" : 0,"query": {"range": {"time": {"gte": 0, // since"lte": 0 // to}}},"aggs": {"agg": { // agg为聚合的名称"terms": { // 聚合的条件为 uid 相同"field": "uid"},"aggs": { // 添加统计指标(Metrics)"avg_duration": { "avg": { // 统计 watch_duration 的平均值"field": "watch_duration" }}}}}
}

response:

{"took": 10,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 100000,"max_score": 0,"hits": []},"aggregations": {"agg": {"buckets": [{"key": 21836334489858688,"doc_count": 4026,"avg_duration": {"value": 12778.882352941177}},{"key": 31489302390368051,"doc_count": 2717,"avg_duration": {"value": 2652.5714285714284}}]}
}

avg_duration.value 表示 watch_duration 的平均值即该用户的平均观看时长。

聚合分页器

在实际应用中用户的数量非常惊人, 不可能通过一次查询得到全部结果因此我们需要分页器分批取回:

GET /view_log/_search
{"size" : 0,"query": {"range": {"time": {"gte": 0, // since"lte": 0 // to}}},"aggs": {"agg": { "terms": { "field": "uid","size": 10000, // bucket 的最大个数"include": { // 将聚合结果分为10页,序号为[0,9], 取第一页"partition": 0,"num_partitions": 10 }},"aggs": { "avg_duration": { "avg": { "field": "watch_duration" }}}}}
}

上述查询与上节的查询几乎完全相同,只是在aggs.agg.terms字段中添加了include字段进行分页。

查询视频uv

单个视频uv

uv是指观看一个视频的用户数(unique visit),与此相对没有按照用户去重的观看数称为pv(page visit)。

用SQL语句来描述:

SELECT video_id, count(*) as pv, count(distinct uid) as uv
FROM view_log
WHERE video_id = #{video_id};

ElasticSearch可以方便的进行count(distinct)查询:

GET /view_log/_search
{"aggs": {"uv": {"cardinality": {"field": "uid"}}}
}

response:

{"took": 255,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 17579,"max_score": 0,"hits": []},"aggregations": {"uv": {"value": 11}}
}

批量查询视频uv

ElasticSearch也可以批量查询count(distinct), 先用SQL进行描述:

SELECT video_id, count(*) as pv, count(distinct uid) as uv
FROM view_log
GROUP BY video_id;

查询:

GET /view_log/_search
{"size": 0,"aggs": {"video": {"terms": {"field": "video_id"},"aggs": {"uv": {"cardinality": {"field": "uid"}}}}}
}

response:

{"took": 313,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 16940,"max_score": 0,"hits": []},"aggregations": {"video": {"buckets": [{"key": 25417499722062, // 视频id"doc_count": 427, // 视频观看次数 pv"uv": {"value": 124 // 观看视频的用户数 uv}},{"key": 72446898144,"doc_count": 744,"uv": {"value":233}}]}}
}

Having查询

SQL可以使用HAVING语句根据聚合结果进行过滤,ElasticSearch可以使用pipeline aggregations达到此效果不过语法较为繁琐。

根据 count 进行过滤

使用SQL查询观看超过200次的视频:

SELECT video_id, count(*) as view_count
FROM view_log
GROUP BY video_id
HAVING count(*) > 200;
GET /view_log/_search
{"size": 0,"aggs": {"view_count": {"terms": {"field": "video_id"},"aggs": {"having": {"bucket_selector": {"buckets_path": { // 选择 view_count 聚合的 doc_count 进行过滤"view_count": "_count"},"script": {"source": "params.view_count > 200"}}}}}}
}

response:

{"took": 83,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 775,"max_score": 0,"hits": []},"aggregations": {"view_count": {"buckets": [{"key": 35025417499764062,"doc_count": 529},{"key": 19913672446898144,"doc_count": 759}]}}
}

ElasticSearch实现类似HAVING查询的关键在于使用bucket_selector选择聚合结果进行过滤。

根据其它指标进行过滤

接下来我们尝试查询平均观看时长大于5分钟的视频, 用SQL描述该查询:

SELECT video_id FROM view_log
GROUP BY video_id
HAVING avg(watch_duration) > 300;
GET /view_log/_search
{"size": 0,"aggs": {"video": {"terms": {"field": "video_id"},"aggs": {"avg_duration": {"avg": {"field": "watch_duration"} },"avg_duration_filter": {"bucket_selector": {"buckets_path": {"avg_duration": "avg_duration"},"script": {"source": "params.avg_duration > 200"}}  }}}}
}

response:

{"took": 137,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 255,"max_score": 0,"hits": []},"aggregations": {"video": {"buckets": [{"key": 5417499764062,"doc_count": 91576,"avg_duration": {"value": 103}},{"key": 19913672446898144,"doc_count": 15771,"avg_duration": {"value": 197}}]}}
}

转载于:https://www.cnblogs.com/Finley/p/9499534.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/397169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bg感_【0328】BG推文 | 5本我在逃生游戏里养娃娃+岁月缱绻已无你+关于我比女主苏这回事+消失的白月光又回来了等...

大家多多支持原文&#xff01;以下内容多为网络搜集&#xff0c;非商业用途。版权归原作者所有&#xff0c;侵联&#xff01;BG文《我在逃生游戏里养娃娃》作者&#xff1a;鹤舫闲人《岁月缱绻已无你》作者&#xff1a;酒爷《关于我比女主苏这回事》作者&#xff1a;欢何极《消…

android 屏幕最小宽度_AndroidTV屏幕适配-smallestWidth(最小宽度) 限定符

背景前几天接到一个需求&#xff0c;把项目上的原来的2k屏幕适配到4k屏幕。我采用的是smallestWidth最小宽度限定符进行适配的我们项目的。1&#xff0c;smallestWidth 限定符适配原理系统都是根据限定符去寻找对应的 dimens.xml 文件。例如在最小宽度为 720dp 的设备上&#x…

mysql 组合索引

MySQL单列索引是我们使用MySQL数据库中经常会见到的&#xff0c;MySQL单列索引和组合索引的区别可能有很多人还不是十分的了解&#xff0c;下面就为您分析两者的主要区别&#xff0c;供您参考学习。 为了形象地对比两者&#xff0c;再建一个表&#xff1a; CREATE TABLE myInde…

cmake使用总结(转)---工程主目录CMakeList文件编写

在linux 下进行开发很多人选择编写makefile 文件进行项目环境搭建&#xff0c;而makefile 文件依赖关系复杂&#xff0c;工作量很大&#xff0c;搞的人头很大。采用自动化的项目构建工具cmake 可以将程序员从复杂的makefile 文件中解脱出来。cmake 根据内置的规则和语法来自动生…

微信开发者工具 wxmi修改模版颜色_十款高效好用的在线网页工具,提升你的办公效率...

大家好&#xff0c; 我是阿毛&#xff0c;今天给大家推荐高效办公的10个在线网页工具&#xff0c;可以不用下载安装很多app&#xff0c;也不用在电脑上装很多软件。在线制作精彩视频操作非常简单&#xff0c;选择模板&#xff0c;上传照片然后点击制作等待完成就可以了&#xf…

三星ml1660拆机图解_三星s6拆机图解介绍

三星s6拆机图解介绍三星s6怎么拆机?不管你是手机维修者还是狂热的手机玩家&#xff0c;相信对您手中的三星s6内部构造和组装步骤应该都是非常有兴趣的吧?今天绿茶通过Fixit发布的三星s6拆机教程来和大家一起分享一下三星s6拆机步骤&#xff0c;从三星s6的内部构造一起来了解一…

Ajax请求利用jsonp实现跨域

跨域: js有一个同源限制,简单说来源不一样的话就无法相互间交互.那么怎么算来源不一样呢, 举个例子:浏览器访问-->服务器A--->得到页面A---页面A中的js脚本只能访问服务器A的资源(相同域名和端口,此外域名与对应的ip也算不同源,要么都域名,要么都ip). 以上就是js的跨域问…

[转]使用Navicat for Oracle工具连接oracle的

使用Navicat for Oracle工具连接oracle的 这是一款oracle的客户端的图形化管理和开发工具&#xff0c;对于许多的数据库都有支持。之前用过 Navicat for sqlserver,感觉很好用&#xff0c;所以下载了Oracle版的用。上网查看了一下这个工具可以用于任何版本 8i 或以上的 Oracle …

微信小程序基于第三方插件微信同声传译,以及一些问题解决办法

使用之前首先得在微信微信小程序后台添加插件&#xff0c;获取插件的appid 名称 使用时在app.json文件添加插件配置 1 plugins: { 2 WechatSI: { 3 version: 0.1.0, 4 provider: wx069ba97219f66d99 5 } 6 } 其次就是在使用的页面进行调用 在index.js外…

TF卡里删掉文件后内存没变大_内存卡损坏怎么修复?数据恢复方法教程

内存卡损坏怎么修复&#xff1f;内存卡又叫SD卡&#xff0c;是一种很轻便小巧的便携存储装置&#xff0c;往往内置于各种便携媒体设备内部。内存卡本身具有坚固、抗冲击等外部特性和读写快、空间大等内部特性&#xff0c;但是内存卡因为每天都要读写大量数据很容易从内部发生损…

apollo持久化sentinel_Spring Cloud Alibaba基础教程:Sentinel使用Apollo存储规则

上一篇我们介绍了如何通过Nacos的配置功能来存储限流规则。Apollo是国内用户非常多的配置中心&#xff0c;所以&#xff0c;今天我们继续说说Spring Cloud Alibaba Sentinel中如何将流控规则存储在Apollo中。使用Apollo存储限流规则Sentinel自身就支持了多种不同的数据源来持久…

Lintcode: Unique Paths

C dp 递推式&#xff1a;dp[i][j] dp[i-1][j] dp[i][j-1] 初值&#xff1a;dp[i][j] 1&#xff0c;i0 or j0 空间优化&#xff1a;省掉一维 1 class Solution {2 public:3 /**4 * param n, m: positive integer (1 < n ,m < 100)5 * return an integer6…

idea 如何隐藏/展示不想看到的文件

隐藏&#xff1a;在 Ignore files and folders中添加想要过滤的文件或文件夹名称 展示隐藏文件&#xff1a; 在过滤列表中删除掉文件或者文件夹就好了 转载于:https://www.cnblogs.com/mengjianzhou/p/6177897.html

BZOJ2286: [Sdoi2011]消耗战(虚树)

BZOJ2286: [Sdoi2011]消耗战 Time Limit: 20 Sec   Memory Limit: 512 MB Description 在一场战争中&#xff0c;战场由n个岛屿和n-1个桥梁组成&#xff0c;保证每两个岛屿间有且仅有一条路径可达。现在&#xff0c;我军已经侦查到敌军的总部在编号为1的岛屿&#xff0c;而且…

Java基础知识:Java实现Map集合二级联动4

comboBox.setModel(new DefaultComboBoxModel(getProvince())); // 添加省份信息 final JLabel label new JLabel(); label.setText("省/直辖市"); label.setBounds(155, 30, 66, 18); panel.add(label); final JLabel label_1 new JLabel(); label_1.setText(&quo…

linux QT 结束当前进程_Qt编写控件属性设计器7-串口采集

一、前言数据源是组态软件的核心灵魂&#xff0c;少了数据源&#xff0c;组态就是个花架子没卵用&#xff0c;一般数据源有三种方式获取&#xff0c;串口、网络、数据库&#xff0c;至于数据规则是什么&#xff0c;这个用户自己指定&#xff0c;本设计器全部采用第一个字节作为…

magento2邮件调试方法

order mail 直接打印到页面上 位置 vendor\magento\module-sales\Model\Order\Email\Sender.php Magento\Sales\Model\Order\Email\Sender::prepareTemplate() 添加代码 $objectManager \Magento\Framework\App\ObjectManager::getInstance(); $templateFactory $objectManag…

python多进程怎么样_Python执行多进程任务的方法

Python的多进程可以借助from multiprocessing import Pool来实现。简而言之分为这样几步&#xff1a;导入包from multiprocessing import Pool编写任务函数。def 任务函数(参数)实例化进程池并设置进程数。poolPool(欲设置的进程数)开始布置任务&#xff0c;把多个任务添加进多…

JAVA多线程之Synchronize 关键字原理

image众所周知 Synchronize 关键字是解决并发问题常用解决方案&#xff0c;有以下三种使用方式: 同步普通方法&#xff0c;锁的是当前对象。同步静态方法&#xff0c;锁的是当前 Class 对象。同步块&#xff0c;锁的是 {} 中的对象。实现原理&#xff1a;JVM 是通过进入、退出对…

iOS-数据持久化-第三方框架FMDB的使用

FMDB简单介绍 一、简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象&#xff0c;省去了很多麻烦、冗余的C语言代码 对比苹果自带的Core Data框架&#xff0c;更加轻量级和灵活 提供了多线程安全…