本節將詳細介紹DSL全文搜索。
全文查詢包括如下幾種模式:
- match query
標準的全文檢索模式,包含模糊匹配、前綴或近似匹配等。 - match_phrase query
與match query類似,但只是用來精確匹配的短語。 - match_phrase_prefix query
與match_phrase查詢類似,但是在最後一個單詞上執行通配符搜索。 - multi_match query
支持多字段的match query。 - common terms query
相比match query,消除停用詞與高頻詞對相關度的影響。 - query_string query
查詢字符串方式 - simple_query_string query
簡單查詢字符串方式
本節目錄
- 1、match query詳解
- 2、match_phrase query
- 3、match phrase prefix query
- 4、multi match query
- 5、common terms query
- 6、query_string query
- 6.1 多字段支持(multi field)
- 6.2 支持通配符
- 6.3 支持正則表達式
- 6.4 鄰近查詢(可前可後)
- 6.5 範圍查詢
- 6.6 搜索字符串權重提升
- 6.7 boolean運算
- 6.8 分組(grouping)
- 6.9 轉義字符
- 6.10 空查詢
- 6.11 query_string示例
- 7、simple_query_string query
1、match query詳解
1.1 match query使用示例與基本工作原理
全文索引查詢,這意外着首先會對待查字符串(查詢條件)進行分詞,然後再去匹配,返回結果中會待上本次匹配的關聯度分數。
例如存在這樣一條數據:
"_source":{
"post_date":"2009-11-16T14:12:12",
"message":"trying out Elasticsearch",
"user":"dingw2"
}
使用如下查詢條件:
"query": {
"match" : {
"message" : "this out Elasticsearch"
}
}
其JAVA代碼對應:
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("message", "this out elasticsearch"));
其大體步驟如下:
首先對this out Elasticsearch分詞,最終返回結果爲 this、out、Elasticsearch,然後分別去庫中進行匹配,默認只要一個匹配,就認爲匹配,但會加入一個匹配程度(關聯度),用scoce分數表示。
1.2 match query常用參數詳解
- operator(操作類型)
可選值爲:Operator.OR 和 Operator.AND。表示對查詢字符串分詞後,返回的詞根列表,OR只需一個滿足及認爲匹配,而AND則需要全部詞根都能匹配,默認值爲:Operator.OR。 - minimum_should_match 最少需要匹配個數。
在操作類型爲Operator.OR時生效,指明分詞後的詞根,至少minimum_should_match 個詞根匹配,則命中。
"match" : {
"message" : "this out Elasticsearch",
“minimum_should_match ”:“3”
}
此時由於this詞根並不在原始數據"trying out Elasticsearch"中,又要求必須匹配的詞根個數爲3,故本次查詢,無法命中。minimum_should_match 可選值如下:
Type | Example | Description |
---|---|---|
Integer | 3 | 直接數字,不考慮查詢字符串分詞後的個數。如果分詞的個數小於3個,則無法匹配到任何條目。 |
Negative integer | -2 | 負數表示最多不允許不匹配的個數。也就是需要匹配的個數爲(total-2)。 |
Negative percentage | -25% | 百分比,表示需要匹配的詞根佔總數的百分比。 |
Percentage | 75% | 允許不匹配的個數佔總數的百分比。 |
Combination | 3<90% | 如果查詢字符串分詞的個數小於等於3(前面的整數),則只要全部匹配則返回,如果分詞的個數大於3個,則只要90%的匹配即可。 |
Multiple combinations | 2<-25% 9<-3 | 支持多條件表達式,中間用空格分開。該表達式的意義如下:1、如果分詞的個數小於等於2,則必須全部匹配;如果大於2小於9,則除了25%(注意負號)之外都需要滿足。2、如果大於9個,則只允許其中3個不滿足。 |
- analyzer
設置分詞器,默認使用字段映射中定義的分詞器或elasticsearch默認的分詞器。 - lenient
是否忽略由於數據類型不匹配引起的異常,默認爲false。例如嘗試用文本查詢字符串查詢數值字段,默認會拋出錯誤。 - fuzziness
模糊匹配。 - zero_terms_query
默認情況下,如果分詞器會過濾查詢字句中的停用詞,可能會造成查詢字符串分詞後變成空字符串,此時默認的行爲是無法匹配到任何文檔,如果想改變該默認情況,可以設置zero_terms_query=all,類似於match_all,默認值爲none。 - cutoff_frequency
match查詢支持cutoff_frequency,允許指定絕對或相對的文檔頻率:- OR:高頻單詞被放入“或許有”的類別,僅在至少有一個低頻(低於cutoff_frequency)單詞滿足條
件時才積分; - AND:高頻單詞被放入“或許有”的類別,僅在所有低頻(低於cutoff_frequency)單詞滿足條件時才積分。該查詢允許在運行時動態處理停用詞而不需要使用停用詞文件。它阻止了對高頻短語(停用詞)的評分/迭代,並且只在更重要/更低頻率的短語與文檔匹配時纔會考慮這些文檔。然而,如果所有查詢條件都高於給定的cutoff_frequency,則查詢將自動轉換爲純連接(and)查詢,以確保快速執行。
cutoff_frequency取值是相對於文檔的總數的小數[0…1),也可以是絕對值[1, +∞)。
- OR:高頻單詞被放入“或許有”的類別,僅在至少有一個低頻(低於cutoff_frequency)單詞滿足條
- Synonyms(同義詞)
可在分詞器中定義同義詞,具體同義詞將在後續章節中會單獨介紹。
1.3 match query示例
public static void testMatchQuery() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("twitter");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.matchQuery("message", "is out Elasticsearch")
.zeroTermsQuery(ZeroTermsQuery.ALL)
.operator(Operator.OR)
.minimumShouldMatch("4<90%")
).sort(new FieldSortBuilder("post_date").order(SortOrder.DESC))
.docValueField("post_date", "epoch_millis");
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
2、match_phrase query
與match query類似,但只是用來精確匹配的短語。
其主要工作流程:首先,Elasearch(lucene)會使用分詞器對全文本進行分詞(返回一個一個的詞根(順序排列)),然後同樣使用分詞器對查詢字符串進行分析,返回一個一個的詞根(順序性)。如果能在全字段中能夠精確找到與查詢字符串通用的詞根序列,則認爲匹配,否則認爲不匹配。
舉例如下:
如果原文字段message:“quick brown fox test we will like to you”,則使用標準分詞器(analyzer=standard)返回的結果如下:
curl -X GET "192.168.1.10:9200/_analyze" -H 'Content-Type: application/json' -d'
{
"tokenizer" : "standard",
"text" : "quick brown fox test we will like to you",
"attributes" : ["keyword"]
}'
得出如下結果:
{
"tokens":[
{
"token":"quick",
"start_offset":0,
"end_offset":5,
"type":"<ALPHANUM>",
"position":0
},
{
"token":"brown",
"start_offset":6,
"end_offset":11,
"type":"<ALPHANUM>",
"position":1
},
{
"token":"fox",
"start_offset":12,
"end_offset":15,
"type":"<ALPHANUM>",
"position":2
},
{
"token":"test",
"start_offset":16,
"end_offset":20,
"type":"<ALPHANUM>",
"position":3
},
{
"token":"we",
"start_offset":21,
"end_offset":23,
"type":"<ALPHANUM>",
"position":4
},
{
"token":"will",
"start_offset":24,
"end_offset":28,
"type":"<ALPHANUM>",
"position":5
},
{
"token":"like",
"start_offset":29,
"end_offset":33,
"type":"<ALPHANUM>",
"position":6
},
{
"token":"to",
"start_offset":34,
"end_offset":36,
"type":"<ALPHANUM>",
"position":7
},
{
"token":"you",
"start_offset":37,
"end_offset":40,
"type":"<ALPHANUM>",
"position":8
}
]
}
其詞根具有順序性(詞根序列)爲quick、brown、fox、test 、we 、will、 like、 to 、you,
如果查詢字符串爲 quick brown,分詞後的詞根序列爲 quick brown,則是原詞根序列的子集,則匹配。
如果查詢字符串爲 quick fox,分詞後的詞根序列爲 quick fox,與原詞根序列不匹配。如果指定slop屬性,設置爲1,則匹配,其表示每一個詞根直接跳過一個詞根形成新的序列,與搜索詞根進行比較,是否匹配。
如果查詢字符串爲quick fox test,其特點是quick與原序列跳過一個詞brown,但fox後面不跳過任何次,與test緊挨着,如果指定slop=1,同樣能匹配到文檔,但查詢字符串quick fox test will,卻匹配不到文檔,說明slop表示整個搜索詞根中爲了匹配流,能跳過的最大次數。
按照match_phrase的定義,與match query的區別一個在與精確匹配,一個在於詞組term(理解爲詞根序列),故match_phrase與match相比,不會有如下參數:fuzziness、cutoff_frequency、operator、minimum_should_match 這些參數。
3、match phrase prefix query
與match phrase基本相同,只是該查詢模式會對最後一個詞根進行前綴匹配。
GET /_search
{
"query": {
"match_phrase_prefix" : {
"message" : {
"query" : "quick brown f",
"max_expansions" : 10
}
}
}
}
其工作流程如下:首先先對除最後一個詞進行分詞,得到詞根序列 quick brown,然後遍歷整個elasticsearch倒排索引,查找以f開頭的詞根,依次組成多個詞根流,例如(quick brown fox) (quick brown foot),默認查找50組,受參數max_expansions控制,在使用時請設置合理的max_expansions,該值越大,查詢速度將會變的更慢。該技術主要完成及時搜索,指用戶在輸入過程中,就根據前綴返回查詢結果,隨着用戶輸入的字符越多,查詢的結果越接近用戶的需求。
4、multi match query
multi_match查詢建立在match查詢之上,允許多字段查詢。
GET /_search
{
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ] // @1
}
}
}
@1執行作用(查詢)的字段,有如下幾種用法:
- [ “subject”, “message” ] ,表示針對查詢自動對subject,message字段進行查詢匹配。
- [ “title”, “*_name” ],支持通配符,表示對title,以_name結尾的字段進行查詢匹配。
- [ “subject^3”, “message” ],表示subject字段是message的重要性的3倍,類似於字段權重。
4.1 multi_query重要參數詳解
4.1.1 type 屬性
指定multi_query內部的執行方式,取值如下:best_fields、most_fields、cross_fields、phrase、phrase_prefix。
4.1.1.1 best_fields
type默認值,只要其中一個字段匹配則匹配文檔(match query)。但是使用最佳匹配的字段的score來表示文檔的分數,會影響文檔的排序。
例如有如下兩個文檔,id,title,context字段值分別如下:
doc1 : 1 “Quick brown rabbits” “Brown rabbits are commonly seen brown.”
doc2:2 “Keeping pets healthy”, “My quick brown as fox eats rabbits on a regular basis.”
如果查詢字段“brown fox”字符串,兩個文檔的匹配度誰高呢?初步分析如下:查詢字符串"brown fox"會被分詞爲brown、fox兩個詞根,首先brown在doc1的title、context中都能匹配brown,而且次數爲3次,在doc2中,只有在context字段中匹配到brown fox各一次,那哪個相關度(評分score)。
best_fields類型,認爲在同一個字段能匹配到更多的查詢字符串詞根,則認爲該字段更佳。由於doc2的context字段能匹配到兩個查詢詞根,故doc2的匹配度更高,doc2會優先返回,對應測試代碼:
public static void testMultiQueue_best_fields() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("esdemo");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.multiMatchQuery("brown fox", "title","context")
.type(Type.BEST_FIELDS)
);
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
執行的查詢結果如下:
{
"took":4,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"skipped":0,
"failed":0
},
"hits":{
"total":2,
"max_score":0.5753642,
"hits":[
{
"_index":"esdemo",
"_type":"matchquerydemo",
"_id":"2",
"_score":0.5753642,
"_source":{
"context":"My quick brown as fox eats rabbits on a regular basis.",
"title":"Keeping pets healthy"
}
},
{
"_index":"esdemo",
"_type":"matchquerydemo",
"_id":"1",
"_score":0.2876821,
"_source":{
"context":"Brown rabbits are commonly seen.",
"title":"Quick brown rabbits"
}
}
]
}
}
best_fields類型內部會轉換爲(dis_max):
GET /_search
{
"query": {
"dis_max": {
"queries": [
{ "match": { "subject": "brown fox" }},
{ "match": { "message": "brown fox" }}
],
"tie_breaker": 0.3
}
}
}
通常best_fields類型使用單個最佳匹配字段的分數,但如果指定了tie_breaker,則其計算結果如下:最佳匹配字段的分數加上 tie_breaker * _score(其他匹配字段分數)。該查詢模式支持match query相關的參數,例如analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, rewrite, zero_terms_query, cutoff_frequency, auto_generate_synonyms_phrase_query 、fuzzy_transpositions等參數。
best_fields和大多數字段類型都是以字段爲中心的——它們爲每個字段生成匹配查詢。這意味着運算符和minimum_should_match參數將分別應用於每個字段。
4.1.1.2 most_fields
查找匹配任何字段並結合每個字段的_score的文檔,Elasticsearch會爲每個字段生成一個match查詢,然後將它們包含在一個bool查詢中。其算法的核心是各個字段的評分相加作爲文檔的最終得分參與排序。其建議場景是不同字段對同一關鍵字的存儲維度不一樣,例如字段一可能包含同義詞、詞幹、變音符等;字段二可能包含原始詞根,這種情況下綜合各個字段的評分就會顯的更加具有相關性。
該查詢模式支持match query相關的參數,例如analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, rewrite, zero_terms_query, cutoff_frequency, auto_generate_synonyms_phrase_query 、fuzzy_transpositions等參數。
4.1.1.3 phrase、phrase_prefix
這兩種類型score的計算採用best_fields方法,但是其查詢方式分別爲match_phrase、match_phrase_prefix。
4.1.1.4 cross_fields
交叉字段,對於需要匹配多個字段的結構化文檔,cross_fields類型特別有用。例如,在查詢“Will Smith”的first_name和last_name字段時,在一個字段中可能會有“Will”,而在另一個字段中可能會有“Smith”。這聽起來很象most_fields,cross_fields與most_fields的兩個明顯區別如下:
對於opreator、minimum_should_match的作用域不一樣,most_fields是針對字段的,(遍歷每個字段,然後遍歷查詢詞根列表,進行逐一匹配),而cross_fields是針對詞根的,即遍歷詞根列表,搜索範圍是所有字段。
相關性的考量不相同,cross_fields重在這個交叉匹配,對於一組查詢詞根,一部分出現在其中一個字段,另外一部分出現在另外一個字段中,其相關性計算評分將更高。
舉例說明:例如有如下查詢語句:
{
"query": {
"multi_match" : {
"query": "Will Smith",
"type": "cross_fields",
"fields": [ "first_name", "last_name" ],
"operator": "and"
}
}
}
其執行操作時,首先對查詢字符串分析得出will、smith兩個詞根,然後遍歷這兩個詞根,一次對 first_name,last_name 進行匹配,也就是說 opreator、minimum_should_match 這些參數作用2次,而 most_fields 方式,是一個嵌套循環,先遍歷字段,然後對每一個詞根在該字段上進行匹配,在該示例中,opreator、minimum_should_match 這些參數作用4次。
4.1.2 tie_breaker屬性
默認情況下,每個詞彙混合查詢將使用組中任何字段返回的最佳分數,然後將這些分數相加,以給出最終分數。tie_breaker參數可以改變每項混合查詢的默認行爲。tie_breaker可選值如下:
- 0.0 : 默認行爲,使用最佳字段的score。
- 1.0 :所有匹配字段socre的和。
- 0.0 ~ 1.0 : 使用最佳匹配字段的score + (其他匹配字段score) * tie_breaker。
4.1.3 multi_query支持其他match query參數
其他諸如analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, rewrite, zero_terms_query, cutoff_frequency, auto_generate_synonyms_phrase_query 、fuzzy_transpositions等參數,multi_query同樣支持。
5、common terms query
定位:排除停用詞或高頻詞對文檔的匹配影響。提高文檔匹配的精確度,同時不對性能產生影響。
我們來看一個停用詞(高頻詞)對文檔過濾帥選帶來的影響:
查詢字符串中的每個詞根都有搜索成本。搜索“the brown fox”需要三個詞根查詢,分別爲“The”、“brown”和“fox”,所有這些查詢都是針對索引中的所有文檔執行的。
對於“The”的查詢可能匹配許多文檔,因此對相關性的影響要比其他兩個術語小得多。
一種解決這個問題的方法是忽略高頻項。通過將“the”視爲stopword(停用詞),我們可以減少索引大小並減少需要執行的詞彙查詢的數量。這種方法的問題在於,儘管停止語對相關性的影響很小,但它們仍然很重要。
如果我們去掉stopwords,我們就會失去精確性(比如我們無法區分“快樂”和“不快樂”),我們就會失去回憶(比如像“The The The”或“to be or not to be”這樣的文本就不會存在於索引中)。
本文將介紹另外一種方式來解決上述問題:
common terms query 將查詢詞根分爲兩組:更重要的(即低頻詞根)和不那麼重要的(即高頻詞根,以前應該是停止詞)。
首先,它搜索與更重要的詞根(低頻詞)匹配的文檔。這些術語出現在較少的文檔中,對相關性的影響更大,性能更好。
然後,它對不太重要的詞根(高頻詞)執行第二個查詢。但是它並不會計算所有匹配(匹配高頻詞的所有文檔)文檔的相關得分,而是隻計算第一個查詢已經匹配的文檔的_score。通過這種方式,高頻項可以在不付出性能差的代價的情況下改進關聯計算(低頻詞、高頻次相互關聯)。
如果查詢只包含高頻術語,那麼一個查詢將作爲AND(連接)查詢執行,換句話說,所有的詞根都必須滿足。儘管每個單獨的詞根將匹配許多文檔,但術語組合將結果集縮小到最相關的部分,當然單個查詢也可以作爲或以特定的minimum_should_match執行。
詞根根據cutoff_frequency被分配給高頻或低頻組,可以指定爲絕對頻率(>=1)或相對頻率(0.0)。1.0)。
5.1 示例詳解
5.1.1 簡單使用說明
GET /_search
{
"query": {
"common": {
"body": {
"query": "this is bonsai cool",
"cutoff_frequency": 0.001
}
}
}
}
會對查詢詞根 this、is、bonsai、cool4個詞根分詞,詞根頻率小於0.001的bonsail、cool會被當成低頻次,而this、is會被設置爲高頻詞組。由於common term query將詞根分成了低頻組與高頻組,故針對match query的operator、minimum_should_match分別由如下四個參數代替:low_freq_operator、high_freq_operator、minimum_should_match:{low_freq、hign_freq}。
java rest api使用示例如下:
public static void testCommonQuery() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("esdemo");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.commonTermsQuery("context", "this is brown fox")
.cutoffFrequency(0.001f)
.highFreqOperator(Operator.OR)
.highFreqMinimumShouldMatch("3")
.lowFreqOperator(Operator.OR)
.lowFreqMinimumShouldMatch("2")
);
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
6、query_string query
查詢字符串方式。query_string查詢解析器支持對查詢字符串按照操作符進行切割,每個部分獨立分析,例如:
GET /_search
{
"query": {
"query_string" : {
"default_field" : "content",
"query" : "(new york city) OR (big apple)"
}
}
}
query_string的頂層參數如下:
參數名 | 描述 |
---|---|
query | 查詢字符串。 |
default_field | 默認匹配字段,如果未設置,則爲"*",表示所有的字段,也可通過index.query.default_field來統一配置默認字段。 |
default_operator | 設置默認操作類型,可選值:Operator.OR 和 Operator.AND,默認爲Operator.OR。 |
analyzer | 設置分詞器。 |
quote_analyzer | 用於分析查詢字符串中引用的短語的分析器的名稱。對於這些部分,它覆蓋了使用analyzer參數或search_quote_analyzer設置設置的其他分析器。 |
allow_leading_wildcard | 是否允許第一個字符爲通配符(*或?),默認爲允許。 |
enable_position_increments | 是否允許以在結果查詢中啓用位置增量。默認值爲true。 |
fuzzy_max_expansions | 控制模糊匹配的詞根的擴展個數,在match phrase prefix的max_expansions已詳解,默認爲50。 |
fuzziness | 設置爲模糊匹配。 |
fuzzy_prefix_length | 模糊查詢設置前綴長度。默認值爲0。 |
fuzzy_transpositions | 是否開啓模糊互換(ab -> ba)。默認爲true。 |
phrase_slop | match_phrase查詢的slop。 |
boost | 設置查詢的boost值。默認爲1.0。 |
auto_generate_phrase_queries | 是否自動生成短語查詢(match_phrase),默認爲false。 |
analyze_wildcard | 默認情況下,查詢字符串中的通配符項不會被分析。通過將該值設置爲true,還將盡力分析這些值。 |
max_determinized_states | 設置可以創建自動狀態機(正則表達式),默認爲 10000。 |
minimum_should_match | 具體參考match_query的minimum_should_match。 |
lenient | 是否忽略由於數據類型不匹配引起的異常,默認爲false |
time_zone | 時區應用於與日期相關的任何範圍查詢。參見JODA時區。 |
auto_generate_synonyms_phrase_query | 在使用match_phrase_query查詢時開啓同義詞匹配,默認爲true. |
all_fields | 6.4.0版本後已廢棄,使用default_field。 |
6.1 多字段支持(multi field)
query_string支持多字段查詢,可通過fields屬性指定,例如:
GET /_search
{
"query": {
"query_string" : {
"fields" : ["content", "name"],
"query" : "this AND that"
}
}
}
其含義類似於:“query”: “(content:this OR name:this) AND (content:that OR name:that)”。
同時query_string(查詢字符串)模式同樣支持match_query等查詢對應的參數,其工作機制一樣,示例如下:
GET /_search
{
"query": {
"query_string" : {
"fields" : ["content", "name^5"],
// "fields" : ["city.*"],
"query" : "this AND that OR thus",
"tie_breaker" : 0,
"type": "best_fields",
"auto_generate_synonyms_phrase_query" : false (同義詞synonym機制)
}
}
}
6.2 支持通配符
查詢字符串中支持使用通配符?與*,其中?表示的單個字符,而表示0個或多個字符。查詢字符串使用通配符,可能會消耗更多的內存,查詢性能較低下。爲了提高通配符效率,如果只是一個的話,命令就會被重寫爲存在查詢(是否存在文檔),例如fields:["*"]。在關係型數據庫中前置通配符(" ab"),這種查詢是不支持索引查詢的,在es中同樣如此,需要遍歷索引中所有詞根,可以通過allow_leading_wildcard=false來禁用這種查詢。通過將analyze_wildcard設置爲true,將分析以結尾的查詢,並從不同的令牌構建布爾查詢,方法是確保第一個N-1令牌上的精確匹配,以及最後一個令牌上的前綴匹配。
6.3 支持正則表達式
正則表達式可以嵌入到查詢字符串中,方法是將它們包裝成斜槓("/")。注意allow_leading_wildcard無法控制正則表達式的行爲。
6.4 鄰近查詢(可前可後)
雖然短語查詢match_phrase(如“john smith”)要求所有的術語都按照完全相同的順序進行查詢,但是接近查詢允許指定的單詞進一步分開或以不同的順序進行查詢,並且也提供諸如match_query的slop屬性。例如:“fox quick”~5。
6.5 範圍查詢
可以爲日期、數字或字符串字段指定範圍查詢。包含範圍用方括號[min到max]指定,排他範圍用花括號{min到max}指定。例如如下:
- 日期在2012年之內。
date:[2012-01-01 TO 2012-12-31] - 大於等1,小於等5
count:[1 TO 5] - Tags在 alpha 和omega之間,但不包括alpha和omega
tag:{alpha TO omega} - 大於等於10
count:[10 TO *] - 日期小於2012年
date:{* TO 2012-01-01}
6.6 搜索字符串權重提升
使用提高運算符可以設置一個詞根相比其他詞根更加重要(相關性更高)。例如針對查詢字符串"quick2 fox",表明quick這個詞根的重要性比fox重要2倍。該操作符也可以針對短語或組,一個組用()表示,示例如下:“john smith”^2 (foo bar)^4。
6.7 boolean運算
默認情況下,所有詞根都是可選的,只要一個詞根匹配即可(Opreator.OR),從上面得知通過修改default_operator可以改變其默認行爲。ES還支持對查詢字符串進行boolean運算。例如查詢字符串“quick brown +fox -news”表示的含義是:
- fox詞根必須存在。
- news詞根必須不存在。
- quick brown 可選。
也支持常見的布爾運算符AND, OR和NOT(也寫爲&&,||和!),但要注意,它們不遵守通常的優先規則,因此當多個運算符一起使用時,應該使用括號。例如,前面的查詢可以改寫爲:((quick AND fox) OR (brown AND fox) OR fox) AND NOT news。
6.8 分組(grouping)
多個詞根或子句可以用括號組合在一起,形成子查詢,例如(quick OR brown) AND fox。
6.9 轉義字符
在ES中,如下字符需要使用轉義符合\,保留字符是:+ - = && || > < !(){ }[]”^ ~ * ?:\ /。
6.10 空查詢
如果查詢字符串爲空或僅包含空白,則查詢將生成空結果集。
6.11 query_string示例
public static void testQueryStringQuery_Query() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("esdemo");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
// QueryBuilders.queryStringQuery("brown -fox")
// QueryBuilders.queryStringQuery("brown^8 fox^2")
QueryBuilders.queryStringQuery("(quick OR brown) AND fox")
.allowLeadingWildcard(false)
.field("context")
.field("title")
// .minimumShouldMatch("1")
);
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
測試情況如下:
目前範圍查詢暫不知如何編寫查詢字符串,但ES專門通過QueryBuilders.rangeQuery(String name)返回RangeQueryBuilder,鄰近查詢未能編寫Demo。
7、simple_query_string query
簡單字符串查詢模式。使用SimpleQueryParser解析上下文的查詢。與常規的query_string查詢不同,simple_query_string查詢永遠不會拋出異常,並丟棄查詢的無效部分。下面是一個例子:
GET /_search
{
"query": {
"simple_query_string" : {
"query": "\"fried eggs\" +(eggplant | potato) -frittata",
"fields": ["title^5", "body"],
"default_operator": "and"
}
}
}
查詢字符串的寫法非常符合(query_string)中定義的,例如查詢字符串中支持boolean運算等。simple_query_string中的頂級參數都定義在org.elasticsearch.index.query.SimpleQueryStringBuilder中,其含義與query_string中類似,在這裏就不重複介紹了。
simple_query_string支持如下寫法。
- +signifies 表示必須包含。
- | signifies 相當於OR。
- negates 相當於非
- " 包裝一些標記以表示搜索的短語
-
- 例如a*,表示前綴匹配
- ( and ) 括號可表示優先級
- ~N after a word 表示模糊匹配舉例,類似於match_phrase slop。
- ~N after a phrase(短語),表示溢出量。
上述這些寫法與在query_string機制一樣。接下來主要再講述query_string不同點。
7.1 flags
simple_query_string支持多個標記來指定應該啓用哪些解析特性。它被指定爲一個|分隔的字符串,例如:
GET /_search
{
"query": {
"simple_query_string" : {
"query" : "foo | bar + baz*",
"flags" : "OR|AND|PREFIX"
}
}
}
可用的flag的列表如下:ALL, NONE, AND, OR, NOT, PREFIX, PHRASE, PRECEDENCE, ESCAPE, WHITESPACE, FUZZY, NEAR, and SLOP。
7.2 使用示例
public static void testSimpleQueryString_Query() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("esdemo");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.simpleQueryStringQuery("brown -fox")
);
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
關於es 的全文檢索就介紹到這裏了。
歡迎加筆者微信號(dingwpmz),加羣探討,筆者優質專欄目錄:
1、源碼分析RocketMQ專欄(40篇+)
2、源碼分析Sentinel專欄(12篇+)
3、源碼分析Dubbo專欄(28篇+)
4、源碼分析Mybatis專欄
5、源碼分析Netty專欄(18篇+)
6、源碼分析JUC專欄
7、源碼分析Elasticjob專欄
8、Elasticsearch專欄(20篇+)
9、源碼分析MyCat專欄