How to fuzzy match email or telephone by Elasticsearch?(如何通过 Elasticsearch 模糊匹配电子邮件或电话?)
问题描述
我想通过 Elasticsearch 对电子邮件或电话进行模糊匹配.例如:
I want to make fuzzy match for email or telephone by Elasticsearch. For example:
匹配所有以 @gmail.com
或
匹配所有以136开头的电话.
match all telephone startwith 136.
我知道我可以使用通配符,
I know I can use wildcard,
{
"query": {
"wildcard" : {
"email": "*gmail.com"
}
}
}
但是性能很差.我尝试使用正则表达式:
but the performance is very poor. I tried to use regexp:
{"query": {"regexp": {"email": {"value": "*163\.com*"} } } }
但不起作用.
有没有更好的方法来制作它?
Is there better way to make it?
curl -XGET 本地主机:9200/user_data
curl -XGET localhost:9200/user_data
{
"user_data": {
"aliases": {},
"mappings": {
"user_data": {
"properties": {
"address": {
"type": "string"
},
"age": {
"type": "long"
},
"comment": {
"type": "string"
},
"created_on": {
"type": "date",
"format": "dateOptionalTime"
},
"custom": {
"properties": {
"key": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"gender": {
"type": "string"
},
"name": {
"type": "string"
},
"qq": {
"type": "string"
},
"tel": {
"type": "string"
},
"updated_on": {
"type": "date",
"format": "dateOptionalTime"
},
}
}
},
"settings": {
"index": {
"creation_date": "1458832279465",
"uuid": "Fbmthc3lR0ya51zCnWidYg",
"number_of_replicas": "1",
"number_of_shards": "5",
"version": {
"created": "1070299"
}
}
},
"warmers": {}
}
}
映射:
{
"settings": {
"analysis": {
"analyzer": {
"index_phone_analyzer": {
"type": "custom",
"char_filter": [ "digit_only" ],
"tokenizer": "digit_edge_ngram_tokenizer",
"filter": [ "trim" ]
},
"search_phone_analyzer": {
"type": "custom",
"char_filter": [ "digit_only" ],
"tokenizer": "keyword",
"filter": [ "trim" ]
},
"index_email_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [ "lowercase", "name_ngram_filter", "trim" ]
},
"search_email_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [ "lowercase", "trim" ]
}
},
"char_filter": {
"digit_only": {
"type": "pattern_replace",
"pattern": "\\D+",
"replacement": ""
}
},
"tokenizer": {
"digit_edge_ngram_tokenizer": {
"type": "edgeNGram",
"min_gram": "3",
"max_gram": "15",
"token_chars": [ "digit" ]
}
},
"filter": {
"name_ngram_filter": {
"type": "ngram",
"min_gram": "3",
"max_gram": "20"
}
}
}
},
"mappings" : {
"user_data" : {
"properties" : {
"name" : {
"type" : "string",
"analyzer" : "ik"
},
"age" : {
"type" : "integer"
},
"gender": {
"type" : "string"
},
"qq" : {
"type" : "string"
},
"email" : {
"type" : "string",
"analyzer": "index_email_analyzer",
"search_analyzer": "search_email_analyzer"
},
"tel" : {
"type" : "string",
"analyzer": "index_phone_analyzer",
"search_analyzer": "search_phone_analyzer"
},
"address" : {
"type": "string",
"analyzer" : "ik"
},
"comment" : {
"type" : "string",
"analyzer" : "ik"
},
"created_on" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"updated_on" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"custom": {
"type" : "nested",
"properties" : {
"key" : {
"type" : "string"
},
"value" : {
"type" : "string"
}
}
}
}
}
}
}
推荐答案
一个简单的方法是创建一个使用 n-gram 令牌过滤器 用于电子邮件(=> 见下文 index_email_analyzer 和 search_email_analyzer + email_url_analyzer 用于精确的电子邮件匹配)和 edge-ngram 标记过滤器 用于手机(=> 见下文 index_phone_analyzer 和 search_phone_analyzer).
An easy way to do this is to create a custom analyzer which makes use of the n-gram token filter for emails (=> see below index_email_analyzer and search_email_analyzer + email_url_analyzer for exact email matching) and edge-ngram token filter for phones (=> see below index_phone_analyzer and search_phone_analyzer).
完整的索引定义如下.
PUT myindex
{
"settings": {
"analysis": {
"analyzer": {
"email_url_analyzer": {
"type": "custom",
"tokenizer": "uax_url_email",
"filter": [ "trim" ]
},
"index_phone_analyzer": {
"type": "custom",
"char_filter": [ "digit_only" ],
"tokenizer": "digit_edge_ngram_tokenizer",
"filter": [ "trim" ]
},
"search_phone_analyzer": {
"type": "custom",
"char_filter": [ "digit_only" ],
"tokenizer": "keyword",
"filter": [ "trim" ]
},
"index_email_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [ "lowercase", "name_ngram_filter", "trim" ]
},
"search_email_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [ "lowercase", "trim" ]
}
},
"char_filter": {
"digit_only": {
"type": "pattern_replace",
"pattern": "\\D+",
"replacement": ""
}
},
"tokenizer": {
"digit_edge_ngram_tokenizer": {
"type": "edgeNGram",
"min_gram": "1",
"max_gram": "15",
"token_chars": [ "digit" ]
}
},
"filter": {
"name_ngram_filter": {
"type": "ngram",
"min_gram": "1",
"max_gram": "20"
}
}
}
},
"mappings": {
"your_type": {
"properties": {
"email": {
"type": "string",
"analyzer": "index_email_analyzer",
"search_analyzer": "search_email_analyzer"
},
"phone": {
"type": "string",
"analyzer": "index_phone_analyzer",
"search_analyzer": "search_phone_analyzer"
}
}
}
}
}
现在,让我们一点一点地剖析它.
Now, let's dissect it one bit after another.
对于 phone 字段,其想法是使用 index_phone_analyzer 索引电话值,它使用边缘 ngram 标记器来索引电话号码的所有前缀.因此,如果您的电话号码是 1362435647,则会生成以下令牌:1、13、136、<代码>1362、13624、136243、1362435、13624356、13624356代码>、<代码>136243564代码>、<代码>1362435647代码>.
For the phone field, the idea is to index phone values with index_phone_analyzer, which uses an edge-ngram tokenizer in order to index all prefixes of the phone number. So if your phone number is 1362435647, the following tokens will be produced: 1, 13, 136, 1362, 13624, 136243, 1362435, 13624356, 13624356, 136243564, 1362435647.
然后在搜索时我们使用另一个分析器 search_phone_analyzer 它将简单地获取输入号码(例如 136)并将其与 phone 字段匹配使用简单的 match 或 term 查询:
Then when searching we use another analyzer search_phone_analyzer which will simply take the input number (e.g. 136) and match it against the phone field using a simple match or term query:
POST myindex
{
"query": {
"term":
{ "phone": "136" }
}
}
对于 email 字段,我们以类似的方式进行,因为我们使用 index_email_analyzer 索引电子邮件值,它使用 ngram 令牌过滤器,这将产生可以从电子邮件值中获取的所有可能的不同长度(1 到 20 个字符之间)的标记.例如:john@gmail.com 将被标记为 j, jo, joh, ...,gmail.com, ..., john@gmail.com.
For the email field, we proceed in a similar way, in that we index the email values with the index_email_analyzer, which uses an ngram token filter, which will produce all possible tokens of varying length (between 1 and 20 chars) that can be taken from the email value. For instance: john@gmail.com will be tokenized to j, jo, joh, ..., gmail.com, ..., john@gmail.com.
然后在搜索时,我们将使用另一个名为 search_email_analyzer 的分析器,它将获取输入并尝试将其与索引标记进行匹配.
Then when searching, we'll use another analyzer called search_email_analyzer which will take the input and try to match it against the indexed tokens.
POST myindex
{
"query": {
"term":
{ "email": "@gmail.com" }
}
}
email_url_analyzer 分析器未在此示例中使用,但我已将其包含在内,以防您需要匹配确切的电子邮件值.
The email_url_analyzer analyzer is not used in this example but I've included it just in case you need to match on the exact email value.
这篇关于如何通过 Elasticsearch 模糊匹配电子邮件或电话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何通过 Elasticsearch 模糊匹配电子邮件或电话?
- 导入具有可变标题的 Excel 文件 2021-01-01
- 如何使用 pip 安装 Python MySQLdb 模块? 2021-01-01
- 使用 Oracle PL/SQL developer 生成测试数据 2021-01-01
- 在SQL中,如何为每个组选择前2行 2021-01-01
- SQL 临时表问题 2022-01-01
- 以一个值为轴心,但将一行上的数据按另一行分组? 2022-01-01
- 如何将 Byte[] 插入 SQL Server VARBINARY 列 2021-01-01
- 更改自动增量起始编号? 2021-01-01
- 远程 mySQL 连接抛出“无法使用旧的不安全身份验证连接到 MySQL 4.1+"来自 XAMPP 的错误 2022-01-01
- 如何将 SonarQube 6.7 从 MySQL 迁移到 postgresql 2022-01-01
