下面是ES做传统意义上的模糊查询的两种方式,我们分析下优劣势
1:将字段设置为keyword类型,使用wildcard实现模糊查询,如果数据量较大,这种方式模糊查询效率是非常低的,所以实际案例中其实是不太实用的,除非你的数据量只有几十万,完全不用考虑效率问题,而且ES限制单个词条不能超过32766个字节,那么超过10000多字符的文章是不能被全部索引到的,那么模糊查询时就查不到没有索引到的关键词。
2:实用match_phrase查询,设置slop为0,配合单字分词实现模糊查询效果。
第二种方式最关键的是我们要实现单字符的分词,通常很多人认为标准分词器就是单字分词,事实上stander分词器只能对中文实现单字分词,对英文与数字是不能单字符分词的,而且本身就是忽略标点符号的,这样的话用match_phrase实现模糊查询其实就有误差了,例如 “中国最美,丽江盛景”,这个时候我们搜索“美丽”也一样能搜到,因为他本身忽略了标点符号,或者搜索数字或者字母时也一样没有办法跟传统的模糊查询保持一致。
所以经过测试,推荐使用ngram自定义配置实现单字分词效果,分析器配置入下
"analysis": {
"analyzer": {
"charSplit": {
"type": "custom",
"tokenizer": "my_ngram_tokenizer",
"filter": [
"lowercase"
],
"char_filter": [
"html_strip"
]
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": "1",
"max_gram": "1",
"token_chars": [
"letter",
"digit",
"punctuation"
]
}
}
}
这样我们可以把所有的字符都单字分词,然后配合match_phrase就能实现一个真正意义上的模糊查询,这种搜索效率是比wildcard要高出很多。
上面两种方式都可以实现模糊查询的效果,第一种方式缺点就是效率太低,而且字段长度太大没有办法全部索引到。再看下第二种方式的问题
1.使用ngram单字分词会导致索引量增加(测试发现基本会翻倍甚至更多),相应的分片数与硬件配置要求需要增加。
2.使用单字符分词会使同义词查询失效,甚至影响相似性查询等操作,当然,一般来说要模糊查询也就不会考虑同义词查询了。
3.继承了传统模糊查询的问题,如搜索“8年抗战”相关内容,直接搜索关键词“8年”,会搜索到包含“2018年”的内容,这样显然不是你要的结果,但是模糊查询就是这样的效果。
4.field_data也是基于倒排索引实现功能,如有聚合或者排序等操作,也会使用单字符效果,如:某字段存储汉字“中国”,“美国”,但类型为text,这个时候如果要按照国家来聚合查询数据,单字段分词结果就会不准确,就是说聚合与排序也会用单字分词后的索引去做聚合与排序,结果自然也就有偏差了.
以上就是两种模糊查询的方式对比,实际环境里还是需要按照实际的需求与环境决定怎样选择,各位大神如果有更好的方式欢迎交流分享!
继续阅读 »
下面是ES做传统意义上的模糊查询的两种方式,我们分析下优劣势
1:将字段设置为keyword类型,使用wildcard实现模糊查询,如果数据量较大,这种方式模糊查询效率是非常低的,所以实际案例中其实是不太实用的,除非你的数据量只有几十万,完全不用考虑效率问题,而且ES限制单个词条不能超过32766个字节,那么超过10000多字符的文章是不能被全部索引到的,那么模糊查询时就查不到没有索引到的关键词。
2:实用match_phrase查询,设置slop为0,配合单字分词实现模糊查询效果。
第二种方式最关键的是我们要实现单字符的分词,通常很多人认为标准分词器就是单字分词,事实上stander分词器只能对中文实现单字分词,对英文与数字是不能单字符分词的,而且本身就是忽略标点符号的,这样的话用match_phrase实现模糊查询其实就有误差了,例如 “中国最美,丽江盛景”,这个时候我们搜索“美丽”也一样能搜到,因为他本身忽略了标点符号,或者搜索数字或者字母时也一样没有办法跟传统的模糊查询保持一致。
所以经过测试,推荐使用ngram自定义配置实现单字分词效果,分析器配置入下
"analysis": {
"analyzer": {
"charSplit": {
"type": "custom",
"tokenizer": "my_ngram_tokenizer",
"filter": [
"lowercase"
],
"char_filter": [
"html_strip"
]
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": "1",
"max_gram": "1",
"token_chars": [
"letter",
"digit",
"punctuation"
]
}
}
}
这样我们可以把所有的字符都单字分词,然后配合match_phrase就能实现一个真正意义上的模糊查询,这种搜索效率是比wildcard要高出很多。
上面两种方式都可以实现模糊查询的效果,第一种方式缺点就是效率太低,而且字段长度太大没有办法全部索引到。再看下第二种方式的问题
1.使用ngram单字分词会导致索引量增加(测试发现基本会翻倍甚至更多),相应的分片数与硬件配置要求需要增加。
2.使用单字符分词会使同义词查询失效,甚至影响相似性查询等操作,当然,一般来说要模糊查询也就不会考虑同义词查询了。
3.继承了传统模糊查询的问题,如搜索“8年抗战”相关内容,直接搜索关键词“8年”,会搜索到包含“2018年”的内容,这样显然不是你要的结果,但是模糊查询就是这样的效果。
4.field_data也是基于倒排索引实现功能,如有聚合或者排序等操作,也会使用单字符效果,如:某字段存储汉字“中国”,“美国”,但类型为text,这个时候如果要按照国家来聚合查询数据,单字段分词结果就会不准确,就是说聚合与排序也会用单字分词后的索引去做聚合与排序,结果自然也就有偏差了.
以上就是两种模糊查询的方式对比,实际环境里还是需要按照实际的需求与环境决定怎样选择,各位大神如果有更好的方式欢迎交流分享!
收起阅读 »