match_phrase
句子中包含hello
或world
的都會(huì)被搜索出:
GET /my_index/address/_search
{
query: {match:"hello world"}
}
句子中包含hello world
的會(huì)被搜索出:
GET /my_index/address/_search
{
query: {match_phrase:"hello world"}
}
也就是說hello world 必須相鄰鸣个。
再看一個(gè)例子:
GET /my_index/address/_search
{
query: {match_phrase:{content:"hello world", slop: 2}}
}
這個(gè)搜索hello es world
也會(huì)被搜索出來灾杰,因?yàn)橹虚g間隔的詞數(shù)為1 < 2∫ス猓可以通過指定slot來控制移動(dòng)詞數(shù)罩锐。
執(zhí)行過程:
match_phrase執(zhí)行過程:
1.如match搜索一樣進(jìn)行分詞侦高,
2.對分詞后的單詞到field中去進(jìn)行搜索(多個(gè)term匹配)停巷。這一步返回每個(gè)單詞對應(yīng)的doc,并返回這些單詞在對應(yīng)的doc中的位置恕酸,
3.對返回的doc進(jìn)行第一步的篩選堪滨,找到每個(gè)單詞都在同一個(gè)field的doc。
4.對第3步進(jìn)行篩選后的doc進(jìn)行再一次的篩選蕊温,選回位置符合要求的doc。比如,對于match_phrase囚枪,就是找到后一個(gè)單詞的位置比前一個(gè)單詞的位置大1∶巳或者移動(dòng)次數(shù)<slot的文檔。
5.proximity match(使用slot)原理一樣了讨,只是第四位對位置進(jìn)行篩選時(shí)的方法不同捻激。
比如要搜索“hello world”
- 分詞為 hello 和 world
- 分別對term hello和world去搜索。返回兩者匹配到的文檔量蕊。
- 第一次篩選铺罢,取兩個(gè)的交集艇挨。
- 繼續(xù)篩選残炮,對于match_phrase,就是找到后一個(gè)單詞world的位置比前一個(gè)單詞hello的位置大1的文檔
prefix
- 在搜索之前它不會(huì)分析查詢字符串缩滨,它認(rèn)為傳入的前綴就是想要查找的前綴
- 默認(rèn)狀態(tài)下势就,前綴查詢不做相關(guān)度分?jǐn)?shù)計(jì)算,它只是將所有匹配的文檔返回脉漏,然后賦予所有相關(guān)分?jǐn)?shù)值為1苞冯。它的行為更像是一個(gè)過濾器而不是查詢。兩者實(shí)際的區(qū)別就是過濾器是可以被緩存的侧巨,而前綴查詢不行舅锄。
- 只能找到反向索引中存在的術(shù)語
prefix的原理:
需要遍歷所有倒排索引,并比較每個(gè)term是否已所指定的前綴開頭司忱。
比如皇忿,
Term: Doc IDs:
-------------------------
"SW5 0BE" | 5
"W1F 7HW" | 3
"W1V 3DG" | 1
"W2F 8HW" | 2
"WC1N 1LZ" | 4
-------------------------
GET /my_index/address/_search
{
"query": {
"prefix": {
"postcode": "W1"
}
}
}
搜索過程:
為了支持前綴匹配,查詢會(huì)做以下事情:
- 掃描術(shù)語列表并查找到第一個(gè)以 W1 開始的術(shù)語坦仍。
- 搜集關(guān)聯(lián)的ID
- 移動(dòng)到下一個(gè)術(shù)語
- 如果這個(gè)術(shù)語也是以 W1 開頭鳍烁,查詢跳回到第二步再重復(fù)執(zhí)行,直到下一個(gè)術(shù)語不以 W1 為止繁扎。
如果以w1開頭的term很多幔荒,那么會(huì)有嚴(yán)重的性能問題。但是如果term比較小集合梳玫,可以放心使用爹梁。
wildcard
- 工作原理和prefix相同,只不過它在1不是只比較開頭提澎,它能支持更為復(fù)雜的匹配模式姚垃。
- 它使用標(biāo)準(zhǔn)的 shell 模糊查詢:? 匹配任意字符,* 匹配0個(gè)或多個(gè)字符虱朵。
GET /my_index/address/_search
{
"query": {
"regexp": {
"postcode": "W[0-9].+" #1
}
}
}
這也意味著我們需要注意與前綴查詢中相同的性能問題莉炉,執(zhí)行這些查詢可能會(huì)消耗非常多的資源钓账,所以我們需要避免使用左模糊這樣的模式匹配(如,foo 或 .foo 這樣的正則式)
注意:
prefix絮宁、wildcard 和 regrep 查詢是基于術(shù)語操作的梆暮,如果我們用它們來查詢分析過的字段(analyzed field),他們會(huì)檢查字段里面的每個(gè)術(shù)語绍昂,而不是將字段作為整體進(jìn)行處理啦粹。
match_phrase_prefix
這種查詢的行為與 match_phrase 查詢一致,不同的是它將查詢字符串的最后一個(gè)詞作為前綴使用窘游。
比如:
{
"match_phrase_prefix" : {
"brand" : "johnnie walker bl"
}
}
- johnnie
- 跟著 walker
- 跟著 一個(gè)以 bl 開始的詞(prefix)
與 match_phrase 一樣唠椭,它也可以接受 slop 參數(shù)讓相對詞序位置不那么嚴(yán)格:
{
"match_phrase_prefix" : {
"brand" : {
"query": "walker johnnie bl", #1
"slop": 10
}
}
}
我們可以通過設(shè)置 max_expansions 參數(shù)來限制前綴擴(kuò)展的影響,一個(gè)合理的值是可能是50:
{
"match_phrase_prefix" : {
"brand" : {
"query": "johnnie walker bl",
"max_expansions": 50
}
}
}
參數(shù)max_expansions控制著可以與前綴匹配的術(shù)語的數(shù)量
另一個(gè)即時(shí)搜索的方法是忍饰,使用 Ngram部分匹配
, 這種方法會(huì)增加索引的開銷贪嫂,但是會(huì)加快查詢速度。具體可以自行查閱艾蓝。