使用 Elasticsearch 的 NGram 分词器处理模糊匹配
接到一个任务:用 Elasticsearch 实现搜索银行支行名称的功能。大概就是用户输入一截支行名称或拼音首字母,返回相应的支行名称。比如,用户输入"工行"或者"gh",我需要返回"工行XXX分行"类似这样的结果。
我心里嘀咕着:数据库不是支持通配符查询吗?为什么不直接用数据库查询?
说归说,但是任务还是要完成的。之前有在网上看过一篇文章,主要就是说用 Elasticsearch 处理通配符查询不太适合,然后我在评论中看到作者推荐了一个分词器 NGram。
这个分词器可以让通配符查询和普通的查询一样迅速,因为该分词器在数据索引阶段就把所有工作做完了:
An n-gram can be best thought of as a moving window on a word. The n stands for a length. If we were to n-gram the word quick, the results would depend on the length we have chosen:
- Length 1 (unigram): [ q, u, i, c, k ]
- Length 2 (bigram): [ qu, ui, ic, ck ]
- Length 3 (trigram): [ qui, uic, ick ]
- Length 4 (four-gram): [ quic, uick ]
- Length 5 (five-gram): [ quick ]
若要使用 NGram 分词器作为某个字段的分词器,可在索引创建时指定,也可以更新映射关系,以下展示如何在索引创建时指定 NGram 分词器。
{
"settings": {
"analysis": {
"analyzer": {
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer"
}
},
"tokenizer": {
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 1,
"max_gram": 30,
"token_chars": [
"letter",
"digit"
]
}
}
}
},
"mappings": {
"_default_": {
"properties": {
"Name": {
"type": "string",
"analyzer": "ngram_analyzer"
}
}
}
}
}
当某个字段的 analyzer 被指定为 ngram_analyzer,这个字段的查询就都会变成通配符查询,无论是 term 还是 match。
比如,POST /index/type
{
"query": {
"term": {"Name": "工商"}
}
}
会得到"中国工商银行XXX分行"。
比如,POST /index/type
{
"query": {
"match": {"Name": "工商"}
}
}
会得到"中国工商银行XXX分行"、"工行XXX分行"、"中国招商银行XXX分行"。
match 查询会对关键词进行分词,而 Lucene 的默认中文分词就是把每个中文字拆开,这样会变成对"工"、"商"两个字做通配符查询。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux/Unix关于时间和时间戳的命令行
- git文件管理心得分享
- Linux如何实现断点续传文件功能
- Xshell实现Windows上传文件到Linux主机的方法
- Linux中的EXT系列文件系统格式详解
- Linux中hexdump命令用法
- CentOS7挂载新数据盘的完整步骤
- Linux下安装Keepalived及原理分析
- centos6搭建gitlab的方法步骤
- Linxu服务器上安装JDK 详细步骤
- linux 不改变目录结构移动 home 目录到新分区的操作方法
- ubuntu14.04安装opencv3.0.0的操作方法
- Linux中让alias设置永久生效的方法详解
- Centos系统下“无法打开并写入文件”问题的解决
- 如何在Linux下设置录音笔时间