使用 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 的默认中文分词就是把每个中文字拆开,这样会变成对"工"、"商"两个字做通配符查询。

文章转载自 开源中国社区[http://www.oschina.net]

时间: 2024-10-11 16:47:49

使用 Elasticsearch 的 NGram 分词器处理模糊匹配的相关文章

如何在Elasticsearch中安装中文分词器(IK+pinyin)

如果直接使用Elasticsearch的朋友在处理中文内容的搜索时,肯定会遇到很尴尬的问题--中文词语被分成了一个一个的汉字,当用Kibana作图的时候,按照term来分组,结果一个汉字被分成了一组. 这是因为使用了Elasticsearch中默认的标准分词器,这个分词器在处理中文的时候会把中文单词切分成一个一个的汉字,因此引入中文的分词器就能解决这个问题. 本篇文章按照下面的内容进行描述: 分词器的作用 安装IK 简单的测试 模拟测试 安装elasticsearch-analysis-piny

elasticsearch 2.3.4 java API 连接,ik分词器,设置集群节点,创建index,mapping的几种方式

1.默认集群连接 Client client = TransportClient.builder().build() .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300)); 2.自定义集群连接 Settings settings = Settings.settingsBuilder().put("cluster.name", &qu

Elasticsearch——分词器对String的作用

关于String类型--分词与不分词 在Elasticsearch中String是最基本的数据类型,如果不是数字或者标准格式的日期等这种很明显的类型,其他的一般都会优先默认存储成String.同样的数据类型,Elasticsearch也提供了多种存储与分词的模式,不同的模式应用于不同的场景. 很多人在初次使用Elasticsearch时,都会很纳闷... 为什么我存储的一句话,却查询不到? 为什么我输入了汉语单词,只能一个字一个字的匹配? 为什么我的url查询不到? 等等,这些都与是否分词.使用

Elasticsearch 使用中文分词

本文演示了如何使用IK Analysis 插件来实现在 Elasticsearch 中的中文分词功能. 使用中文分词 在"Spring Boot应用企业级博客系统"课程中(http://coding.imooc.com/class/125.html),所有的博客功能都已经完成了.读者朋友们开始愉快地使用博客来发表博客了.但如果朋友们足够细心的话,发现在输入中文的标签的时候,存在一定的问题. 比如,当我们想将某个博客标记为"大神"时,博客系统却将这个单词粗暴的分成了如

ElasticSearch 安装 ik 分词插件

       在搜索领域,中文分词一直都是难题.经过很多大牛的不懈努力,还是出现了一些很不错的中文分词器,比如本文提到的IK.本文主要基于ES,安装ik分词插件.        一.IK简介     IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本.最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件.从3.0版本开 始,IK发展为面向Java的公用分

如何开发自己的搜索帝国之安装ik分词器

 Elasticsearch默认提供的分词器,会把每个汉字分开,而不是我们想要的根据关键词来分词,我是中国人 不能简单的分成一个个字,我们更希望 "中国人","中国","我"这样的分词,这样我们就需要安装中文分词插件,ik就是实现这个功能的. elasticsearch-analysis-ik 是一款中文的分词插件,支持自定义词库. 现在开始安装ik分词器,安装之前,先说明一些变化: 之前可以在node节点上配置index默认的分词器,如果是多节

使用Mongo Connector和Elasticsearch实现模糊匹配

[编者按]本篇博文作者Luke Lovett是MongoDB公司的Java工程师,他展示了Mongo Connector经过2年发展后的蜕变--完成连接器两端的同步更新.期间,Luke还展示如何通过Elasticsearch实现模糊匹配. 以下为译文: 介绍 假设你正在运行MongoDB.太好了,现在已经可以为基于数据库的所有查询进行精确匹配了.现在,设想你正要在你的应用中建立一个文本搜索功能,它必须去除拼写错误这个噪音,最终可能会得到一个相近的结果.为此,这个令人生畏的任务,你需要在Lucen

Lucene 3.6.2入门(5) 自定义停用词分词器和同义词分词器

首先是用于显示分词信息的HelloCustomAnalyzer.java package com.jadyer.lucene; import java.io.IOException; import java.io.StringReader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.toke

Lucene 3.6.2入门(4) 中文分词器

package com.jadyer.lucene; import java.io.IOException; import java.io.StringReader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.SimpleAnalyzer; import org.apache.lucene.analysis.StopAnalyzer; import org.apache.lucene