带家好,我是马儿,这次来讲一下最近遇到的一个问题

我司某个环境的es中被导入了重复数据,导致查询的时候会出现一些重复数据,所以要我们几个开发想一些解决方案,我们聊了聊,相出了下面一些方案:

1.从源头解决:导入数据时进行唯一性校验

2.从数据解决:清洗数据,将重复的数据查出后清理,然后入库

3.从查询解决:查询时筛选重复数据

我就从查询着手,找到了聚合查询的方法

聚合(Aggregations)

聚合功能为ES带来了统计分析的能力,类似于SQL语言中的group by,avg,sum等函数

桶(Buckets):符合条件的文档的集合,相当于SQL中的group by

桶的概念在很多地方有应用,比如桶排序,HashMap的实现中数组也可看作桶,等等等等

示例:

根据city,对twitter索引的文档进行分组

aggs:聚合

my:自定义名称

terms:根据结果分类

field:筛选字段

city:需要分类的字段

GET /twitter/doc/_search
{
"from": 0,
"size": 0,
"aggs": {
"my":{
"terms":{
"field": "city"
}
}
}
}

结果中聚合的部分:

计算出了类型和命中的数量

"aggregations": {
"my": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "北京",
"doc_count": 105
},
{
"key": "上海",
"doc_count": 1
}
]
}
}

但这不是只有统计结果吗,我要的是筛选后的数据啊

top_hits指标聚合器

top_hits指标聚合器跟踪要聚合的最相关文档,可以有效地用于通过存储桶聚合器按某些字段对结果集进行分组。

选项:

from-要获取的第一个结果的偏移量。

size-每个存储桶要返回的最匹配匹配项的最大数目。 默认情况下,返回前三个匹配项。

排序-匹配的热门匹配的排序方式。 默认情况下,命中按主要查询的分数排序。

示例:

根据city,对twitter索引的文档进行分组、根据age进行排序、结果只包含user+age+city,然后显示每组的一条数据

aggs:聚合

my:自定义名称

terms:根据结果分类

field:筛选字段

city:需要分类的字段

sort:排序

age:排序依据字段

order:排序方式

desc:降序

_source includes:结果包含的字段

size:每组显示的数量

{
"from": 0,
"size": 0,
"aggs": {
"my":{
"terms":{
"field": "city"
},
"aggs":{
"my_top_hits":{
"top_hits":{
"sort": [
{
"age": {
"order": "desc"
}
}
],
"_source": {
"includes": [
"user",
"age",
"city"
]
},
"size":1
}
}
}
}
}
}

结果中聚合的部分:

"aggregations": {
"my": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "北京",
"doc_count": 105,
"my_top_hits": {
"hits": {
"total": 105,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW5jwgirrweXGTc7-cPA",
"_score": null,
"_source": {
"city": "北京",
"user": "朝阳区-老王",
"age": 50
},
"sort": [
50
]
}
]
}
}
},
{
"key": "上海",
"doc_count": 1,
"my_top_hits": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW5jwiM1rweXGTc7-cPB",
"_score": null,
"_source": {
"city": "上海",
"user": "虹桥-老吴",
"age": 90
},
"sort": [
90
]
}
]
}
}
}
]
}
}

但是光使用terms,我添加了多个字段后查不出来东西了都,难道这样还不行吗

使用script进行聚合

常规的聚合无法在聚合中进行复杂操作,所以要加入脚本

示例:

修改terms中内容为下,将三个条件拼接起来

"terms":{
"script": "doc['user.keyword'].value + '#' + doc['age'].value + '#' +doc['city'].value"
},

查询结果:

key:拼接的条件

doc_count:每组重复的数目

"aggregations": {
"my": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "双榆树-张三#20#北京",
"doc_count": 101,
"my_top_hits": {
"hits": {
"total": 101,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW9lr8sBP5iHlpen8GYt",
"_score": null,
"_source": {
"city": "北京",
"user": "双榆树-张三",
"age": 20
},
"sort": [
20
]
}
]
}
}
},
{
"key": "东城区-李四#30#北京",
"doc_count": 1,
"my_top_hits": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW5jwaOIrweXGTc7-cO-",
"_score": null,
"_source": {
"city": "北京",
"user": "东城区-李四",
"age": 30
},
"sort": [
30
]
}
]
}
}
},
{
"key": "东城区-老刘#30#北京",
"doc_count": 1,
"my_top_hits": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW5jwXhcrweXGTc7-cO9",
"_score": null,
"_source": {
"city": "北京",
"user": "东城区-老刘",
"age": 30
},
"sort": [
30
]
}
]
}
}
},
{
"key": "朝阳区-老王#50#北京",
"doc_count": 1,
"my_top_hits": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW5jwgirrweXGTc7-cPA",
"_score": null,
"_source": {
"city": "北京",
"user": "朝阳区-老王",
"age": 50
},
"sort": [
50
]
}
]
}
}
},
{
"key": "朝阳区-老贾#35#北京",
"doc_count": 1,
"my_top_hits": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW5jwcvBrweXGTc7-cO_",
"_score": null,
"_source": {
"city": "北京",
"user": "朝阳区-老贾",
"age": 35
},
"sort": [
35
]
}
]
}
}
},
{
"key": "虹桥-老吴#90#上海",
"doc_count": 1,
"my_top_hits": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "twitter",
"_type": "doc",
"_id": "AW5jwiM1rweXGTc7-cPB",
"_score": null,
"_source": {
"city": "上海",
"user": "虹桥-老吴",
"age": 90
},
"sort": [
90
]
}
]
}
}
}
]
}
}

可以看到,每组都不一样,我们script真是太强大了

Java实现



使用elasticsearch包中的工具类,将索引中所有字段进行拼接,作为aggregation参数传入查询即可

总结:

本文介绍了es的聚合功能,aggs+top_hits+script就能过滤重复数据,得到唯一结果。

但是这边也有个坑,es聚合本身不支持分页

这个分页以后有机会再说

Elasticsearch去重查询/过滤重复数据(聚合)的更多相关文章

  1. 手把手教你如何用java8新特性将List中按指定属性排序,过滤重复数据

    在java中常常会遇到这样一个问题,在实际应用中,总会碰到对List排序并过滤重复的问题,如果List中放的只是简单的String类型过滤so easy,但是实际应用中并不会这么easy,往往List ...

  2. scrapy过滤重复数据和增量爬取

    原文链接 前言 这篇笔记基于上上篇笔记的---<scrapy电影天堂实战(二)创建爬虫项目>,而这篇又涉及redis,所以又先熟悉了下redis,记录了下<redis基础笔记> ...

  3. sql 查询重复数据,删除重复数据,过滤重复数据

    select * from (SELECT titleid,count(titleid) c FROM [DragonGuoShi].[dbo].[ArticleInfo] group by titl ...

  4. Oracle查询和过滤重复数据

    对数据库某些意外情况,引起的重复数据,如何处理呢? ----------------查重复: select * from satisfaction_survey s and s.project_no ...

  5. MySQL 数据库查询数据,过滤重复数据保留一条数据---(MySQL中的row_number变相实现方法)

    转自: http://www.maomao365.com/?p=10564 摘要: 下文讲述MySQL数据库查询重复数据时,只保留一条数据的方法 实现思路: 在MySQL数据库中没有row_numbe ...

  6. SQL查询去掉重复数据

    本文主要总结数据库去掉重复数据的方法 去掉重复数据的方法: 第一种:distinct 根据单个字段去重,能精确去重: 作用在多个字段时,只有当这几个字段的完全相同时,才能去重: 关键字distinct ...

  7. 爬虫数据使用MongDB保存时自动过滤重复数据

    本文转载自以下网站: 爬虫断了?一招搞定 MongoDB 重复数据 https://www.makcyun.top/web_scraping_withpython13.html 需要学习的地方: Mo ...

  8. sql查询删除重复数据

    数据库UserInfo 删除重复数据 即删除重复的用户名手机号 同一个用户名手机号只保留一个用户 01.根据多个字段查询重复数据 with data1 as( select MobilePhone,N ...

  9. mysql语句删除重复数据,保留一条;查询所有重复数据;查询重复数据的一条,

    //显示重复的所有条 SELECT * FROM 表名 WHERE (字段1,字段2,...) IN (SELECT 字段1,字段2,...FROM 表名 GROUP BY 字段1,字段2,... H ...

随机推荐

  1. Mac打不开inkscape怎么办

    本经验题目提到的是一款矢量图片编辑软件,对于打开不开的软件,完全可以通过卸载软件后进行安装.这里就从安装以及卸载的过程说明一下这个软件的安装卸载过程. 方法/步骤 打开电脑任意一个浏览器图标,进入浏览 ...

  2. Unity自定义Log

    有如下两种方式,第一种借助了Unity自身的LogType枚举型:第二种则是纯粹地自己定义: public class Log { public Log(string message, UnityEn ...

  3. [Android-NDK编译] ndk 编译 c++ 兼容性问题汇总整理

    1.__int64找不到符号 采用int64_t来代替: #if defined(__ANDROID__) typedef int64_t __int64; #endif 2.<sys/io.h ...

  4. 设计Weekday类 代码参考

    #include <iostream> using namespace std; class Weekday { private: int num; public: void SetDay ...

  5. apt-key 密钥管理,apt-secure 原理 验证链 验证测试

    apt-key 用于管理Debian Linux系统中的软件包密钥.每个发布的deb包,都是通过密钥认证的,apt-key用来管理密钥. apt-key list 列出已保存在系统中key.包括 /e ...

  6. Rocket - tilelink - toBools

    https://mp.weixin.qq.com/s/UGMH8EoaVcFkkQW-l4HLWg   分析toBools在Intellij中显示为红色的问题.   ​​   1. 问题   在TLA ...

  7. 【JVM】关于OOM的二三事

    组织架构 严格来说,StackOverflowError和OutOfMemoryError都属于错误,而不是异常. java.lang.StackOverflowError public class ...

  8. 【HBase】 常用命令

    创建表 hbase(main):006:0> create 'goods_zc','type' 0 row(s) in 1.3090 seconds => Hbase::Table - g ...

  9. Java实现蓝桥杯历届试题分考场

    历届试题 分考场 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 n个人参加某项特殊考试. 为了公平,要求任何两个认识的人不能分在同一个考场. 求是少需要分几个考场才能满足条件. 输 ...

  10. Linux 文件系统常用命令

    文件系统查看命令df df:查看分区,单位默认是KB df -h 统计目录或文件大小du du /etc/:会列出/etc/目录下的所有子目录所占的空间,最后给出/etc/目录的大小,属于高负载命令, ...