之前我有文章解读:Elasticsearch6.X 去重详解
拿个实战列子看一下:
当下正值高考出成绩,我们拿新闻事件信息作为数据来源。
如下文档_id:1、_id:2、_id:3 是一模一样的数据;_id: 4 是独立数据。
也就是说:去重后数据分两组,一组:[1,2,3]; 另外一组:[4]。
PUT news/_bulk
{"index":{"_id":1}}
{"title":"南开录取通知书亮相,附赠嘉兴莲花种子、一封特殊的信","cont":"今天,南开大学晒出建党百年特别版录取通知书。","url":"https://baijiahao.baidu.com/s?id=1703334751082094750&wfr=spider&for=pc","publish_time":"2021-06-23 13:36"}
{"index":{"_id":2}}
{"title":"南开录取通知书亮相,附赠嘉兴莲花种子、一封特殊的信","cont":"今天,南开大学晒出建党百年特别版录取通知书。","url":"https://baijiahao.baidu.com/s?id=1703334751082094750&wfr=spider&for=pc","publish_time":"2021-06-23 13:36"}
{"index":{"_id":3}}
{"title":"南开录取通知书亮相,附赠嘉兴莲花种子、一封特殊的信","cont":"今天,南开大学晒出建党百年特别版录取通知书。","url":"https://baijiahao.baidu.com/s?id=1703334751082094750&wfr=spider&for=pc","publish_time":"2021-06-23 13:36"}
{"index":{"_id":4}}
{"title":"建党百年特别版!南开大学录取通知书送两粒嘉兴莲花种子","cont":"@南开大学 6月23日消息,建党百年特别版南开大学录取通知书揭秘!","url":"https://www.163.com/dy/article/GD69KNIR0514R9P4.html","publish_time":"2021-06-23 13:25:00"}
# top_hits 子聚合去重
GET news/_search
{
"query": {
"match_all": {}
},
"aggs": {
"type": {
"terms": {
"field": "title.keyword",
"size": 10
},
"aggs": {
"title_top": {
"top_hits": {
"_source": {
"includes": [
"title"
]
},
"sort": [
{
"title.keyword": {
"order": "desc"
}
}
],
"size": 1
}
}
}
}
},
"size": 0
}
# collapse 去重
GET news/_search
{
"query": {
"match_all": {}
},
"collapse": {
"field": "title.keyword"
}
}
源码确认:
的确不支持。
原有的方案和思路都在 scroll 导出数据方面行不通的,只能考虑新的思路了。
这个问题扩展一下,如何让数据写入 Elasticsearch 前去重呢?
说一下我的 Mysql 到 Elasticsearch 同步实战思路:
数据由 Mysql 同步到 Elasticsearch 如何实现去重?
其实也很简单,一旦有了MD5值,将MD5值作为写入 Elasticsearch 的文档 id,就可以完成 Mysql 数据到 Elasticsearch 的去重同步处理。
而下面要着重讲解的 logstash fingerprint filter 插件实现数据去重处理,就是基于刚才的思路实现的。
fingerprint:中文直译为"指纹"。
https://www.elastic.co/guide/en/logstash/current/plugins-filters-fingerprint.html
官方文档强调:
Versioned plugin documentation is not available for plugins released prior to Logstash 6.0.
这是 Logstash 6.X 之后才有的功能。
fingerprint filter 插件是 logstash filter 强大环节中的 58 个核心插件的中间一个插件。
其核心功能:创建一个或多个字段的一致哈希(指纹)并将结果存储在新字段中。
当文档插入 Elasticsearch 时,可以使用此插件创建一致的文档 ID。
也就是说,如果两个或者后续多个文档的指纹一致,则写入 Elasticsearch 的 _id 一致(前提 ES ID是明确指定使用指纹),所以相同指纹数据写入 Elasticsearch 会覆盖,间接实现了写入去重。
下面我们先实战,再根据实战讲解核心参数意思,大家理解可能更顺畅、通透一些。
写在配置文件:logstash_print.conf 中(配置文件名称自己定义就可以)。
input {
# Read all documents from Elasticsearch
elasticsearch {
hosts => "172.21.0.14:19022"
index => "news"
query => '{ "sort": [ "_doc" ] }'
}
}
filter {
fingerprint {
key => "1234ABCD"
method => "SHA256"
source => ["title", "cont", "url", "publish_time"]
target => "[@metadata][generated_id]"
concatenate_sources => true
}
}
output {
stdout { codec => dots }
elasticsearch {
hosts => "172.21.0.14:19022"
index => "news_after_fingerprint"
document_id => "%{[@metadata][generated_id]}"
}
}
logstash 脚本大家就记住三段论。
如果为true 且 method 不是 UUID 或 PUNCTUATION 时,插件会在进行指纹计算之前将 source 选项中给出的所有字段的名称和值连接成一个字符串。
如果给出 false 和多个源字段,则目标字段将是最后一个源字段的单个指纹。
fingerprint filter 插件是基于现实业务问题而开发的,解决写入去重或者导出去重的业务痛点。我们再看开头两个问题。
fingerprint filter 插件较开头两种去重方案优势体现在:
欢迎留言交流一下您的去重思考。
https://alexmarquardt.com/tag/deduplicate/
本文分享自 铭毅天下Elasticsearch 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!