fingerprint filter 插件——Elasticsearch 去重必备利器

Posted 铭毅天下

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fingerprint filter 插件——Elasticsearch 去重必备利器相关的知识,希望对你有一定的参考价值。

1、实战问题

  • 问题1:es 中 scroll 游标不能与 collapse 共用,有什么办法可以实现 collapse 的效果?

  • 问题2:采集互联网数据有重复数据写入 Elasticsearch,如何去重后放到另外索引?

2、排查思路

2.1 Elasticsearch 去重的几种方式

之前我有文章解读:Elasticsearch6.X 去重详解

  • 方式一:terms 指定字段聚合 + top_hits 子聚合。

  • 方式二:collapse 折叠去重。

拿个实战列子看一下:

当下正值高考出成绩,我们拿新闻事件信息作为数据来源。

如下文档_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"
  }
}

2.2 Elasticsearch scroll 不支持 collapse 确认

源码确认:

的确不支持。

2.3 考虑新方案

原有的方案和思路都在 scroll 导出数据方面行不通的,只能考虑新的思路了。

这个问题扩展一下,如何让数据写入 Elasticsearch 前去重呢?

说一下我的 mysql 到 Elasticsearch 同步实战思路:

  • 数据源:爬虫采集互联网数据(由于是采集数据,难免会有转载等重复数据)。

  • 源数据存储:Mysql。

  • 如何界定重复?基于:发文标题、发文时间、发文正文内容、发文url 组成字段的MD5值作为去重标记。

数据由 Mysql 同步到 Elasticsearch 如何实现去重?

其实也很简单,一旦有了MD5值,将MD5值作为写入 Elasticsearch 的文档 id,就可以完成 Mysql 数据到 Elasticsearch 的去重同步处理。

而下面要着重讲解的 logstash fingerprint filter 插件实现数据去重处理,就是基于刚才的思路实现的。

3、logstash fingerprint filter 插件介绍

fingerprint:中文直译为"指纹"。

https://www.elastic.co/guide/en/logstash/current/plugins-filters-fingerprint.html

3.1 fingerprint filter 插件版本

官方文档强调:

Versioned plugin documentation is not available for plugins released prior to Logstash 6.0.

这是 Logstash 6.X 之后才有的功能。

3.2 fingerprint filter 插件用途

fingerprint filter 插件是 logstash filter 强大环节中的 58 个核心插件的中间一个插件。

其核心功能:创建一个或多个字段的一致哈希(指纹)并将结果存储在新字段中。

当文档插入 Elasticsearch 时,可以使用此插件创建一致的文档 ID。

也就是说,如果两个或者后续多个文档的指纹一致,则写入 Elasticsearch 的 _id 一致(前提 ES ID是明确指定使用指纹),所以相同指纹数据写入 Elasticsearch 会覆盖,间接实现了写入去重。

下面我们先实战,再根据实战讲解核心参数意思,大家理解可能更顺畅、通透一些。

4、logstash fingerprint filter 去重实战

4.1 同步脚本

写在配置文件: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]}"
    }
}

4.1.1 脚本讲解

logstash 脚本大家就记住三段论。

  • 第一:input,代表输入(读取端),本实例自然是基于 Elasticsearch 读。

  • 第二:filter,代表中间处理,那就是指纹处理部分。

  • 第三:output,代表输出(写入端),本实例还是写入 Elasticsearch,只不过会写入新的索引 news_after_fingerprint。

4.1.2 filter 环节核心参数讲解

  • key => "1234ABCD",代表当前指纹的唯一值。

  • method => "SHA256",指纹生成方式。

  • source => ["title", "cont", "url", "publish_time"],生成指纹的基础字段名称。

  • target => "[@metadata][generated_id]":将存储生成的指纹的字段的名称,后面output 环节会使用。该字段的任何当前内容都将被覆盖。

  • concatenate_sources => true

如果为true 且 method 不是 UUID 或 PUNCTUATION 时,插件会在进行指纹计算之前将 source 选项中给出的所有字段的名称和值连接成一个字符串。

如果给出 false 和多个源字段,则目标字段将是最后一个源字段的单个指纹。

4.2 同步实操

4.3 成功标记

5、小结

fingerprint filter 插件是基于现实业务问题而开发的,解决写入去重或者导出去重的业务痛点。我们再看开头两个问题。

  • 问题1 答案:不用 collapse,用 fingerprint filter 插件将数据转存为另外索引,然后 scroll 遍历输出就可以。

  • 问题2 答案:用 fingerprint filter 插件将数据转存为另外索引即可。

fingerprint filter 插件较开头两种去重方案优势体现在:

  • 能将去重后的数据独立存储为一个索引,且无需额外操作。

  • 方便业务单独处理数据。

欢迎留言交流一下您的去重思考。

参考

https://alexmarquardt.com/tag/deduplicate/

推荐:

更短时间更快习得更多干货!

中国50%+Elastic认证工程师出自于此!

以上是关于fingerprint filter 插件——Elasticsearch 去重必备利器的主要内容,如果未能解决你的问题,请参考以下文章

布隆过滤器(Bloom Filter)与Hash算法

vue el-table和添加全局的filter过滤器,并支持过滤器文字换图标

el-select filterable 啥意思

android修改getprop读取到的ro.build.fingerprint属性

09. pt-fingerprint

android开发中Fingerprint模块浅析