一、前缀搜索
搜索包含KDKE前缀的articleID
GET /forum/article/_search
{
"query": {
"prefix": {
"articleID": {
"value": "KDKE"
}
}
}
}
{
"took": 52,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "forum",
"_type": "article",
"_id": "2",
"_score": 1,
"_source": {
"articleID": "KDKE-B-9947-#kL5",
"userID": 1,
"hidden": false,
"postDate": "2017-01-02",
"tag": [
"java"
],
"tag_cnt": 1,
"view_cnt": 50,
"title": "this is java blog",
"content": "i think java is the best programming language",
"sub_title": "learned a lot of course",
"author_first_name": "Smith",
"author_last_name": "Williams"
}
}
]
}
}
二、前缀搜索的原理
prefix query不计算relevance score,与prefix filter惟一的区别就是,filter会cache bitset
扫描整个倒排索引,举例说明
前缀越短,要处理的doc越多,性能越差,尽量用长前缀搜索
前缀搜索,它是怎么执行的?性能为何差呢?
match"articleID": "KDKE-B-9947-#kL5""articleID": "QQPX-R-3956-#aD8""articleID": "XHDK-A-1293-#fJ3"
全文检索
每一个字符串都须要被分词
KDKE doc1,doc2
KDKE
B
9947
#kL5
QQPX
....
KDKE --> 扫描倒排索引 --> 一旦扫描到
KDKE,就能够停了,由于带
KDKE的就1个doc,已经找到了 --> 没有必要继续去搜索其余的term了
match性能每每是很高的
不分词
"articleID": "KDKE-B-9947-#kL5"java
"articleID": "QQPX-R-3956-#aD8""articleID": "XHDK-A-1293-#fJ3"
KDKE --> 先扫描到了
KDKE-B-9947-#kL5,很棒,找到了一个前缀带
KDKE的字符串 --> 仍是要继续搜索的,由于也许还有其余不少的前缀带
KDKE的字符串 --> 你扫描到了一个前缀匹配的term,不能停,必须继续搜索 --> 直到扫描完整个的倒排索引,才能结束
由于实际场景中,可能有些场景是全文检索解决不了的
KDKE-B-9947-#kL5
KD --> match --> 扫描整个倒排索引,能找到吗
KD --> 只能用prefix
prefix性能不好
三、通配符搜索
跟前缀搜索相似,功能更增强大
5字符-D任意个字符5
5?-*5:通配符去表达更加复杂的模糊搜索的语义
GET /forum/article/_search
{
"query": {
"wildcard": {
"articleID": {
"value": "*Q?PX*8"
}
}
}
}
?:任意字符
*:0个或任意多个字符
性能同样差,必须扫描整个倒排索引,才ok
四、正则搜索
GET forum/article/_search
{
"query": {
"regexp": {
"articleID": "K[A-Z].+"
}
}
}
K[A-Z].+
[0-9]:指定范围内的数字
[a-z]:指定范围内的字母
.:一个字符
+:前面的正则表达式能够出现一次或屡次
wildcard和regexp,与prefix原理一致,都会扫描整个索引,性能不好
主要是给你们介绍一些高级的搜索语法。在实际应用中,能不用尽可能别用。性能太差了。
五、搜索推荐
搜索推荐,search as you type,搜索提示
hello w --> 搜索
hello world
hello we
hello win
hello wind
hello dog
hello cat
hello w -->
hello world
hello we
hello win
hello wind
搜索推荐的功能
百度 --> elas --> elasticsearch --> elasticsearch权威指南
GET forum/article/_search
{
"query": {
"match_phrase_prefix": {
"content": {
"query": "i elas",
"slop":5,
"max_expansions": 1
}
}
}
}
原理跟match_phrase相似,惟一的区别,就是把最后一个term做为前缀去搜索
i就是去进行match,搜索对应的doc
elas,会做为前缀,去扫描整个倒排索引,找到全部
elas开头的doc
而后找到全部doc中,即包含i,又包含
elas开头的字符的doc
根据你的slop去计算,看在slop范围内,能不能让hello w,正好跟doc中的hello和w开头的单词的position相匹配
也能够指定slop,可是只有最后一个term会做为前缀
max_expansions:指定prefix最多匹配多少个term,超过这个数量就不继续匹配了,限定性能
默认状况下,前缀要扫描全部的倒排索引中的term,去查找w打头的单词,可是这样性能太差。能够用max_expansions限定,w前缀最多匹配多少个term,就再也不继续搜索倒排索引了。
尽可能不要用,由于,最后一个前缀始终要去扫描大量的索引,性能可能会不好
六、误拼写时的fuzzy模糊搜索
搜索的时候,可能输入的搜索文本会出现误拼写的状况
doc1: hello world
doc2: hello java
搜索:hallo world
fuzzy搜索技术 --> 自动将拼写错误的搜索文本,进行纠正,纠正之后去尝试匹配索引中的数据
POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "text": "Surprise me!"}
{ "index": { "_id": 2 }}
{ "text": "That was surprising."}
{ "index": { "_id": 3 }}
{ "text": "I wasn't surprised."}
GET /my_index/my_type/_search
{
"query": {
"fuzzy": {
"text": {
"value": "surprize",
"fuzziness": 2
}
}
}
}
surprize --> 拼写错误 --> surprise --> s -> z
surprize --> surprise -> z -> s,纠正一个字母,就能够匹配上,因此在fuziness指定的2范围内
surprize --> surprised -> z -> s,末尾加个d,纠正了2次,也能够匹配上,在fuziness指定的2范围内
surprize --> surprising -> z -> s,去掉e,ing,3次,总共要5次,才能够匹配上,始终纠正不了
fuzzy搜索之后,会自动尝试将你的搜索文本进行纠错,而后去跟文本进行匹配
fuzziness,你的搜索文本最多能够纠正几个字母去跟你的数据进行匹配,默认若是不设置,就是2
GET /my_index/my_type/_search
{
"query": {
"match": {
"text": {
"query": "SURPIZE ME",
"fuzziness": "AUTO",
"operator": "and"
}
}
}
}