Elasticsearch 之(21)前缀搜索、通配符搜索、正则搜索、推荐搜索 和 模糊搜索

1、前缀搜索
搜索包含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"
        }
      }
    ]
  }
}
2、前缀搜索的原理
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"

"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性能很差


3、通配符搜索
跟前缀搜索类似,功能更加强大

5字符-D任意个字符5

5?-*5:通配符去表达更加复杂的模糊搜索的语义

GET /forum/article/_search
{
  "query": {
    "wildcard": {
      "articleID": {
        "value": "*Q?PX*8"
      }
    }
  }
}

?:任意字符
*:0个或任意多个字符

性能一样差,必须扫描整个倒排索引,才ok

4、正则搜索

GET forum/article/_search
{
  "query": {
    "regexp": {
      "articleID": "K[A-Z].+"
    }
  }
}
K[A-Z].+

[0-9]:指定范围内的数字
[a-z]:指定范围内的字母
.:一个字符
+:前面的正则表达式可以出现一次或多次

wildcard和regexp,与prefix原理一致,都会扫描整个索引,性能很差

主要是给大家介绍一些高级的搜索语法。在实际应用中,能不用尽量别用。性能太差了。

5、搜索推荐
搜索推荐,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,就不再继续搜索倒排索引了。

尽量不要用,因为,最后一个前缀始终要去扫描大量的索引,性能可能会很差

6、误拼写时的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"
      }
    }
  }
}


posted @ 2018-05-24 11:20  91vincent  阅读(609)  评论(0编辑  收藏  举报