1、前綴查詢
先輸入數據:
PUT /my_index/address/1 { "postcode": "W1 3DG" } PUT /my_index/address/2 { "postcode": "W2F 8HW" } PUT /my_index/address/3 { "postcode": "W1 7HW" } PUT /my_index/address/4 { "postcode": "WC1N 1LZ" } PUT /my_index/address/5 { "postcode": "SW5 0BE" }
為了找到所有以 W1 開始的郵編,可以使用簡單的 prefix 查詢:
類似於SQL: select * from table where xx like 'xx%';
GET /my_index/address/_search { "query": { "prefix": { "postcode": "W1" } } }
2、短語匹配查詢(match_phrase)
在執行短語匹配查詢時,ElasticSearch引擎首先分析(analyze)查詢字符串,從分析后的文本中構建短語查詢,這意味着必須匹配短語中的所有分詞,並且保證各個分詞的相對位置不變:
POST /_search -d { "from":1, "size":100, "fields":[ "eventname"], "query":{ "match_phrase":{ "eventname":"Open Source" } } }
3、短語前綴匹配查詢(match_phrase_prefix)
除了把查詢文本的最后一個分詞只做前綴匹配之外,match_phrase_prefix和match_phrase查詢基本一樣,參數 max_expansions 控制最后一個單詞會被重寫成多少個前綴,也就是,控制前綴擴展成分詞的數量,默認值是50。擴展的前綴數量越多,找到的文檔數量就越多;如果前綴擴展的數量太少,可能查找不到相應的文檔,遺漏數據。如代碼所示,能夠查到eventname包含"Open Source Hack Night"的文檔。
POST /_search -d { "from":1, "size":100, "fields":[ "eventname" ], "query":{ "match_phrase_prefix":{ "eventname":{ "query":"Open Source hac", "max_expansions":50 } } } }
使用match性能往往是很高的,W1–> 掃描倒排索引 –> 一旦掃描到W1,就可以停了,因為帶W1的就2個doc,已經找到了 –> 沒有必要繼續去搜索其他的term了;
4、通配符與正則表達式查詢
與 prefix 前綴查詢的特性類似, wildcard 通配符查詢也是一種底層基於詞的查詢, 與前綴查詢不同的是它允許指定匹配的正則式。它使用標准的 shell 通配符查詢: ? 匹配任意字符, * 匹配 0 或多個字符。
這個查詢會匹配包含 W1F 7HW 和 W2F 8HW 的文檔:
GET /my_index/address/_search { "query": { "wildcard": { "postcode": "W?F*HW" } } }
? 匹配 1 和 2 , * 與空格及 7 和 8 匹配。
設想如果現在只想匹配 W 區域的所有郵編,前綴匹配也會包括以 WC 開頭的所有郵編,與通配符匹配碰到的問題類似,如果想匹配只以 W 開始並跟隨一個數字的所有郵編, regexp 正則式查詢允許寫出這樣更復雜的模式:
GET /my_index/address/_search { "query": { "regexp": { "postcode": "W[0-9].+" } } }
QueryBuilders.regexpQuery("postcode", "W[0-9].+");
這個正則表達式要求詞必須以 W 開頭,緊跟 0 至 9 之間的任何一個數字,然后接一或多個其他字符。
wildcard和regexp,與prefix原理一致,都會掃描整個索引,性能很差;數據在索引時的預處理有助於提高前綴匹配的效率,而通配符和正則表達式查詢只能在查詢時完成,盡管這些查詢有其應用場景,但使用仍需謹慎。
