老师有个问题想请教一下,我们项目中有个需求是查询出数据集根据某个字段去重后的全部结果,用 collapse 发现很多数据都没查询到,后面发现是去重的这个字段的值太长了,ignore _above默认的是256,而这个字段的值有的有十几万甚至几十万个字符,像这种情况,还有什么比较好的查询去重方法吗?
——来自:死磕Elasticsearch知识星球
https://t.zsxq.com/15t8cCz6s
那么有没有其他的实现方式呢?
在 Elasticsearch 中,Fingerprint(指纹)通常指的是一种机制,用于为数据生成一个唯一的标识符或指纹。这个指纹是基于数据内容的一个哈希值,可用于识别和区分数据项。
在处理大量数据时,尤其是在日志聚合或数据索引的场景中,去重变得非常重要。
Fingerprint 可以帮助识别重复的数据。通过对数据生成指纹,可以确保数据在传输或处理过程中的完整性。
### 定义finger_print processor
PUT _ingest/pipeline/fp_processor
{
"processors": [
{
"fingerprint": {
"fields": [
"content"
]
}
}
]
}
### 创建索引
DELETE news_index
PUT news_index
{
"settings": {
"default_pipeline": "fp_processor"
},
"mappings": {
"properties": {
"content": {
"type": "text"
}
}
}
}
### 批量写入数据
PUT news_index/_bulk
{"index":{"_id":1}}
{"content":"雷军:小米汽车正在试产爬坡阶段,定价“有理由的贵”"}
{"index":{"_id":2}}
{"content":"雷军剧透小米汽车发布会:对标保时捷、特斯拉 定价有点贵身"}
{"index":{"_id":3}}
{"content":"雷军:小米汽车正在试产爬坡阶段,定价“有理由的贵”"}
### 执行检索
POST news_index/_search
召回结果如下:
注意:
关于 Elasticsearch 中的 Fingerprint 分析器(或者称为分词器),一个常见且易于理解的应用场景是在数据清洗过程中用于识别和合并重复的记录。
例如,考虑一个包含用户信息的数据集,其中由于录入错误或不一致的格式,同一用户的多个记录可能以略微不同的方式出现。使用 Fingerprint 分析器,我们可以生成每条记录的唯一指纹,从而轻松识别和合并这些重复的记录。
参见下面的真实举例,在地址或人名数据的去重中,Fingerprint 分析器可以帮助识别本质上相同但表述略有差异的记录。
假设我们有一个包含人名的数据集,由于不同的输入习惯,同一个人名可能有不同的表述方式,比如:
"John Smith"
"smith, john"
"John Smith" (多个空格)
虽然这些记录代表同一个人,但由于格式和空格的差异,它们可能被视为不同的记录。
扩展场景:
为了标准化并识别这些记录,我们可以在 Elasticsearch 中定义一个使用 Fingerprint 分析器的索引。
以下是完整的 DSL 示例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_fingerprint_analyzer": {
"type": "fingerprint",
"stopwords": "_english_"
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "my_fingerprint_analyzer"
}
}
}
}
POST my_index/_bulk
{"index":{"_id":1}}
{"name": "John Smith"}
{"index":{"_id":2}}
{"name": "smith, john"}
{"index":{"_id":3}}
{"name": "John Smith"}
如上DSL 解读如下:在 settings 下定义了一个自定义的分析器 my_fingerprint_analyzer,它使用 Elasticsearch 的 Fingerprint 分析器类型,并配置了英语停用词列表。
"stopwords": "english" 是指在使用某些文本分析器(比如 Fingerprint 分析器)时,应用预定义的英语停用词列表。
停用词是在文本处理中通常被排除的词汇,因为它们过于常见而且通常不携带重要的含义或信息,比如 "the", "is", "at", "which" 等。
POST my_index/_search
POST my_index/_analyze
{
"text": [
"John Smith",
"smith, john",
"John Smith"
],
"field": "name"
}
执行结果如下:
从上面的结果不难看出,即使上述三条记录在某些细节上不同,它们也会生成相同的指纹,从而可以被识别为代表同一用户的记录。
尤其:"smith, john" 也会做字母排序处理,变成“john smith”。
通过这种方式,Fingerprint 分析器帮助我们识别和合并数据集中的重复记录,从而提高数据的一致性和准确性。
Fingerprint 分析器可实现功能列表如下:
将输入文本中的所有字符都被转换为小写,这有助于确保文本处理不受字母大小写的影响,提高数据的一致性。比如,前文中的“john smith”就是例证。
文本中的扩展字符(如重音符号或其他非标准ASCII字符)被转换或移除。这一步骤有助于统一不同格式或编码方式的文本。
文本中的单词(或标记)被按字典顺序排序。排序后,相同的单词组合(无论原始顺序如何)将被视为相同,有助于数据聚类和去重。
重复的单词或标记在排序后被移除。这减少了数据的冗余性,使每个文本的表示更加紧凑和唯一。
经过上述处理后的单词或标记被合并成一个单一的长字符串标记。这样做的目的是创建一个独特的“指纹”,用于表示原始文本。
如果配置了停用词列表,那么常见的停用词(如“the”, “is”, “at”等)将从文本中移除。停用词通常在文本分析中被忽略,因为它们过于常见且不携带特定信息。——比如咱们前面用到的"stopwords": "english"。
继续举例子看一下:
POST my_index/_analyze
{
"text": [
"the the skiing center of the U.S.; If you're going to work hard, now is the time."
],
"field": "name"
}
执行结果如下:
{
"tokens": [
{
"token": "center going hard now skiing time u.s work you're",
"start_offset": 0,
"end_offset": 81,
"type": "fingerprint",
"position": 0
}
]
}
一句话:
还有,如果涉及大文本去重、聚合相关操作,推荐将 fingerprint 用起来!
本文分享自 铭毅天下Elasticsearch 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!