ElasticSearch教程——字首搜尋、萬用字元搜尋、正則搜尋、推薦搜尋 和 模糊搜尋
字首搜尋
搜尋包含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"
"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"
}
}
}
}