前綴的匹配壹般是處理沒有分割的場景,會匹配articleID中以“j”開頭的doc。Prefix不計算相關性分數,只執行過濾操作。與filter的唯壹區別是filter緩存結果,而prefix不緩存。前綴越短,要處理的doc越多,性能越差。
?匹配任何字符,而*匹配0個或更多字符。性能根前綴也壹樣糟糕,必須掃描整個倒排索引。
[0-9]:指定範圍內的數字。
【a-z】:指定範圍內的字幕。
。:壹個字符。
+:前面的正則表達式可以出現壹次或多次。
常規搜索也會掃描整個表,性能會比較差。
模糊性參數的數量調整和修正
通常不會直接使用上面的搜索,但會使用下面的搜索:
在專家系統中,組合條件查詢的使用是搜索引擎搜索數據的壹個有力組成部分。在以前的文章中,簡單地演示了es的查詢語法,但是添加、刪除和修改查詢的基本功能並不能很好地滿足復雜的查詢場景。比如我們期望像mysql壹樣用復雜的條件進行查詢,該怎麽辦?es裏有壹個語法叫bool。通過在bool中拼接es特定的文法,可以做大多數場景下復雜條件的拼接查詢,也叫復合查詢。
首先簡單介紹了專家系統中組合查詢常用的關鍵字。
過濾:過濾,不參與評分。
必須:如果有多個條件,它們必須滿足and和。
Should:如果有多個條件,其中壹個或多個可以是or或OR。
Must_not:與Must相反,必須不滿足所有條件才可以匹配!表示“不”
事件描述
必須
該子句(查詢)必須出現在匹配的文件中,並且將有助於得分。
過濾器
子句(查詢)必須出現在匹配的文檔中。然而,不同於must查詢的分數將被忽略。Filter子句在過濾器上下文中執行,這意味著分數被忽略,並且該子句被考慮用於緩存。
應該
子句(查詢)應該出現在匹配的文檔中。如果bool查詢在查詢上下文中,並且有壹個mustor filter子句,那麽即使沒有匹配的should查詢,文檔也會匹配bool查詢。在這種情況下,這些術語僅用於影響分數。如果bool查詢是壹個篩選器上下文,或者兩者都不存在,則至少有壹個must或filter的should查詢必須與文檔匹配,以匹配bool查詢。這種行為可以通過設置minimum_should_match參數來顯式控制。
千萬不要
子句(查詢)不能出現在匹配的文檔中。該子句在過濾器上下文中執行,這意味著分數被忽略,並且該子句被考慮用於緩存。由於分數被忽略,返回了0的所有文件的分數。
讓我們用實驗來演示上述查詢的相關語法。
1.首先,我們創建壹個索引,並向其中添加壹些數據供以後使用。
我可以在這裏直接批量插入數據,也可以通過PUT的語法插入。
帖子/論壇/文章/_批量
{ "index": { "_id": 1 }}
{ " articleID ":" XHDK-A-1293-# fJ3 "," userID" : 1," hidden": false," postDate ":" 2019-07-01 "," title":"java包含hadoop和spark "," topic":"java" }
{ "index": { "_id": 2 }}
{ "articleID" : "KDKE-B-9947-#kL5 "," userID" : 1," hidden": false," postDate": "2019-07-02 ",title":"php包含admin "," topic":"java和php" }
{ "index": { "_id": 3 }}
{ " articleID ":" JODL-X-1937-# pV7 "," userID" : 2," hidden": false," postDate": "2019-07-03 ",title":"spark是新語言"," topic":"spark可能使用java"}
{ "index": { "_id": 4 }}
{ "articleID" : "QQPX-R-3956-#aD8 "," userID" : 2," hidden": true," postDate": "2019-07-04 ",title":"hadoop可能涉及java "," topic ":"使用的大數據" }
或者使用put語法。
放/論壇/文章/4
{
" articleID": "QQPX-R-3956-#aD8 ",
“userID”:2,
“隱”:真,
" postDate": "2019-07-04 ",
"標題":" hadoop可能涉及java ",
“主題”:“使用大數據”
}
4條數據已成功插入。
2、$ TERM查詢、$ TERM查詢不分詞,這類似於mysql中的where filedName =?語法,也就是精確匹配,比如我們查詢articleid = xhdk-a-1293-# fj3的這個數據。
獲取/論壇/文章/_搜索
{
"查詢":{
"期限":{
" articleid . keyword ":" XHDK-A-1293-# fJ3 "
}
}
}
2.必須查詢,即查詢條件中必須匹配的字段。例如,查詢標題必須包含java數據。
獲取/論壇/文章/_搜索
{
"查詢":{
" bool": {
"必須":[
{"term":{"title":"hadoop"}}
]
}
}
}
找出兩個數據
如果是應該呢?以下語法,即查詢標題中包含hadoop或主題中包含spark,其中壹個即可滿足。
獲取/論壇/文章/_搜索
{
"查詢":{
" bool": {
"應該":[
{"term":{"title":"hadoop"}},
{ "術語":{ "主題":"火花" }}
]
}
}
}
找到了三條數據,
Must和should壹起使用,
最後,壹個更復雜的嵌套查詢,我們先來看看這個sql語句。
選擇*
來自論壇.文章
其中article _ id = ' XHDK-A-1293-# fJ3 '
或者(article _ id = ' JODL-X-1937-# pV7 '和post _ date = ' 2017-01-01 '),
轉換成es對應的復合查詢語法是什麽?在拆分方面,它是壹個should語句的嵌套。
獲取/論壇/文章/_搜索
{
"查詢":{
" bool": {
"應該":[
{
"期限":{
" articleid . keyword ":" XHDK-A-1293-# fJ3 "
}
},
{
" bool": {
"必須":[
{
"期限":{
" articleid . keyword ":" JODL-X-1937-# pV7 "
}
},
{
"期限":{
" post date ":" 2019-07-01 "
}
}
]
}
}
}
}
按照這個思路,如果不知道如何為壹個復雜的查詢構造查詢語句,可以考慮先按照sql的語法進行拆分,然後組織es查詢語句就是壹個很好的突破口。
此時,我們可能會有疑問,復合條件下的$ term查詢和簡單匹配有什麽區別?既然都是查詢,原理上有什麽區別?
我們知道匹配查詢需要全文檢索,而且是全文檢索。當然,如果搜索的字段值不是_analyzed,那麽匹配查詢相當於$ term查詢。例如,在下面的搜索中,因為我們在插入數據時沒有指定title字段,所以默認情況下它是text類型,並且它將被自動分段,所以只要hadoop包含在title中,它就可以被匹配。
獲取/論壇/文章/_搜索
{
"查詢":{
"匹配":{
"標題":" hadoop "
}
}
}
2.在某些情況下,如果我們直接使用match進行查詢,並且希望查詢出來的結果有我們期望的那麽多關鍵詞,那麽我們可以在使用match進行匹配時添加其他條件,以提高結果的匹配精度。
獲取/論壇/文章/_搜索
{
"查詢":{
"匹配":{
"標題":{
「查詢」:「java hadoop」,
“運算符”:“和”
}
}
}
}
匹配的結果包含更多我們期望的關鍵詞,也就是說,我們的查詢結果中包含的關鍵詞可以在查詢中指定。
Es還有其他的語法來達到上面的效果,minimum_should_match。通過這個語法,可以指定匹配的百分比,也就是查詢的關鍵字至少要達到的百分比。下面這個表示所有匹配,只找到壹個結果。
如果我們降低百分比,比如說75%,我們可以看到兩個結果。
3.當然我們也可以把bool和match壹起用,如下。
獲取/論壇/文章/_搜索
{
"查詢":{
" bool": {
"必須":[
{"match": {"title": "java"}}
],
"壹定不能":[
{ "匹配":{ "標題":"火花" }}
]
,“應該”:[
{
"匹配":{
"標題":" php "
}
}
]
}
}
}
這樣,我們也可以更準確地匹配我們期望的查詢結果。
綜上所述,當我們使用match進行查詢時,如果查詢字段包含多個單詞,比如下面這個,
{
" match ":{ " title ":" Java elastic search " }
}
實際上,es會自動將這個匹配查詢轉換成底部的bool Should,指定多個搜索詞,同時使用$ term查詢。轉換後的語法如下。
{
" bool": {
"應該":[
{ "term": { "title": "java" }},
{ " term ":{ " title ":" elastic search " } }
]
}
}
上面提到的with and in match查詢對應的是bool查詢,轉換後的語法如下:$ term+must,
{
"匹配":{
"標題":{
「查詢」:「java elasticsearch」,
“運算符”:“和”
}
}
}
{
" bool": {
"必須":[
{ "term": { "title": "java" }},
{ " term ":{ " title ":" elastic search " } }
]
}
}
對於minimum_should_match的語法,道理也差不多。
{
"匹配":{
"標題":{
「查詢」:「java elasticsearch hadoop spark」,
" minimum_should_match": "75% "
}
}
}
{
" bool": {
"應該":[
{ "term": { "title": "java" }},
{ " term ":{ " title ":" elastic search " } },
{ "term": { "title": "hadoop" }},
{ "term": { "title": "spark" }}
],
“最小_應該_匹配”:3
}
}
我們來看壹個具體的操作例子,也就是說,必須包含至少三個關鍵詞的數據才會出現在搜索結果中。
3.在搜索中,我們有這樣壹個需求,搜索結果中包含java,如果標題中包含hadoop或者spark,就會被優先搜索。同時,如果壹個帖子包含java hadoop,壹個帖子包含java spark,那麽包含hadoop的帖子會比spark先被搜索到。
對於這樣的需求,壹般來說,需要增加某些搜索條件的權重,讓更多符合和滿足我們業務場景的數據在搜索結果中被搜索出來,在es中通過boost關鍵字增加搜索條件的權重。
獲取/論壇/文章/_搜索
{
"查詢":{
" bool": {
"必須":[
{
"匹配":{
"標題":" java "
}
}
],
"應該":[
{
"匹配":{
"標題":{
"查詢":" hadoop "
}
}
},
{
"匹配":{
"標題":{
「查詢」:「火花」,
【助推】:2
}
}
},
{
"匹配":{
"標題":{
"查詢":" php "
}
}
},
{
"匹配":{
"標題":{
「查詢」:「hadoop」,
【助推】:5
}
}
}
]
}
}
}
上面的例子意味著我們對hadoop被包含在搜索的標題中的條件給予更多的權重,hadoop的結果將被限制為被搜索。
4、dis_max語法,也稱為best_field,在某些情況下,如果我們在bool查詢中使用多個字段,但查詢是相同的,可能會導致查詢結果沒有按照我們期望的字段排在前面,即我們只需要將指定字段的內容顯示在前面,如下。
獲取/論壇/文章/_搜索
{
"查詢":{
" bool": {
"應該":[
{ "match": { "title": "java解決方案" }},
{ "match": { "content": "java解決方案" }}
]
}
}
}
標題和內容的搜索條件相同,但是我們希望結果中的標題包含java解決方案的前置顯示,但是直接查詢可能達不到預期的效果。如果使用dis_max進行拼接,
獲取/論壇/文章/_搜索
{
"查詢":{
" dis_max": {
"查詢":[
{ "match": { "title": "java解決方案" }},
{ "match": { "content": "java解決方案" }}
]
}
}
}
這樣,查詢結果更符合期望值,
5.但是使用dis_max,只取壹個查詢的最大值,其他查詢的分數完全忽略。即如果壹個結果在包標題中包含java,而在主題中沒有,另壹個則相反,結果是兩個都包含java。在dis_max文法下,只會得到相關性分數最高的壹個,其他結果不予考慮。此時,如果需要獲取其他包含java的title或topic的結果,可以使用tie_breaker進行進壹步的打包,如下。
獲取/論壇/文章/_搜索
{
"查詢":{
" dis_max": {
"查詢":[
{ "匹配":{ "標題":"火花" }},
{ "match": { "topic": "java"}}
],
“平局決勝”:0.6
}
}
}
這樣,發現了三個結果。總體來說,還是需要結合實際的業務場景來使用。然而,大多數情況下,我們是相愛的。我們還是希望根據我們給定的條件,搜索結果優先考慮包含更多關鍵詞的內容。