elasticsearch7.Xterm查询中文即IK分词器的相关解决办法

  • 问题的产生
  • 问题的原因
  • 回到最初的问题
  • 解决办法


问题的产生

学习elasticsearch时,当进行精确查询时候,我们发现无法对中文词汇进行有效的检索。但是对单个字进行查询却能检索得到。

es 输入中文检索英文_解压缩


es 输入中文检索英文_elasticsearch_02


查询好人没有结果,查询如果换成“好”,“李白是个大好人”就被查到了。

问题的原因

要弄清怎么回事,首先要知道什么是分词器,以及elasticsearch怎么实现的索引。elasticsearch除了存储数据,还为他们建立了一个索引表,类似书籍的目录。

举个栗子:
存储的数据

地址

内容

地址1

good boy

地址2

boy friend

elasticsearch默认的“Standard Analyzer”分词器会将“good boy”分成“good”和“boy”,“boy friend”分成“boy”和“friend”放入索引表
索引表

关键词

地址

good

地址1

boy

地址1 地址2

friend

地址2

当我们查询时,这里我们先说match查询,查询的内容也会被分词

{
	"query":{
		"match":{
			"name":"good friend"
		}
	}
}

它会被分成“good”和“friend”用于查询,只要满足其一都会被返回,所以地址1和地址2的都被返回了,这也是我们百度时明明输入个大概就能检索到许多内容。

那么我们换成精确查询呢,会怎么样?

{
	"query":{
		"term":{
			"name":"good friend"
		}
	}
}

结果就是查不到,因为“good friend”不会被分词,反而作为一个整体去查询,可是索引中并不存在“good friend”这个关键词。

那么怎样实现我想要的查询结果呢?

很简单,使用短语查询的方式。即:phrase query。默认短语中间不能有间隔,但是可使用slop=1来表示中间可以间隔一个term(单词),这个比我们想要的还要灵活,甚至可以决定中间间隔几个单词。

POST /movies/_search
{
  "query": {
    "match_phrase": {
      "title":{
         "query": "one love",
         "slop": 1
      }
    }
  }
}

说了那么多term的意义何在?
事实上term主要是针对“时间”、“数字”等重要不可分割的查询词。他压根就不是用在这的,我也说了这里应该用phrase query。

回到最初的问题

中文查询,默认分词器分割英文是空格为基准分开的,英文恰好是一个一个的单词。但中文却是被分成了一个个字,“苹果”被分成“苹”和“果”

我们match查询“苹果”时能查出“我爱吃苹果”但也会查到“小朋友苹苹喜欢吃果子”,后面那个并不是我们想要的。

解决办法

引入ik分词器,他能将中文正确分词,还可以自定义词库使得他能识别一些新出现的词汇如“奥利给”

操作如下

1.下载地址: https://github.com/medcl/elasticsearch-analysis-ik/releases

注意: es-ik分词插件版本一定要和es安装的版本对应

2.将文件 解压再改名ik上传到linux根目录下。

(1)因为我是smatty远程操控的linux主机,我先将压缩文件改名ik 。

(2)建立一个plugins目录,进入目录并将ik压缩包拖(直接拖进去就能上传,很方便)进去。

es 输入中文检索英文_elasticsearch_03


(3)解压压缩包,这里可能没有解压缩的工具,安装方法:

es 输入中文检索英文_分词器_04


(4)解压缩

es 输入中文检索英文_elasticsearch_05


(5)把解压的ik文件拷贝到elasticsearch安装包下的plugins下

es 输入中文检索英文_解压缩_06


根据自己的情况可以上网查询ik分词器的导入方法。

ik分词器有两种模式“ik_max_word”和“ik_smart”可以试验下他们的效果,你自己就能看出区别

es 输入中文检索英文_分词器_07


es 输入中文检索英文_解压缩_08


es 输入中文检索英文_分词器_09

下面还有一大堆,截不下啦

你以为现在就结束了吗?

当然没有,你还得设置当前索引的mapping和setting,来决定他建立索引表所使用的分词器analyzer(就是分“李白是个大好人”的),以及查询时的查询数据所用的分词器search_analyzer(分“好人”的,用了ik分词器,“好人”不会再分成“好”和“人”了)

setting中还可以设置分片和副本,这里我就不细说了

es 输入中文检索英文_解压缩_10


es 输入中文检索英文_es 输入中文检索英文_11


es 输入中文检索英文_解压缩_12


这里就可以用term查询到好人了,但是意义不大,因为我们知道phrase query就可以办到并且因为引入ik查询器,也避免了“苹果”时能查出“我爱吃苹果”但也会查到“小朋友苹苹喜欢吃果子”的问题。

书写不易,一键三连。