ES 21 - Elasticsearch的高級檢索語法 (包括term、prefix、wildcard、fuzzy、boost等)


1 term query - 索引詞檢索

1.1 term query - 不分詞檢索

term query: 把檢索串當作一個整體來執行檢索, 即不會對檢索串分詞.

term是完全匹配檢索, 要用在不分詞的字段上, 如果某個field在映射中被分詞了, term檢索將不起作用.
所以, 不分詞的field, 要在mapping中設置為不分詞.

—— ES 5.x之后, 為每個text類型的字段新增了名為keyword的子字段, 是不分詞的, 默認保留256個字符.

—— 可以使用keyword字段進行term檢索. 示例:

GET shop/_search
{
    "query": {
        "term": {
            "name.keyword": "Java編程思想"
        }
    }
}

1.2 terms query - in檢索

terms, 相當於多個term檢索, 類似於SQL中in關鍵字的用法, 即在某些給定的數據中檢索:

GET shop/_search
{
    "query": {
        "terms": {
            "name.keyword": [
                "Java編程思想", "Java並發編程的藝術"
            ]
        }
    }
}

2 prefix query - 前綴檢索

prefix query, 就是前綴檢索. 比如商品name中有多個以"Java"開頭的document, 檢索前綴"Java"時就能檢索到所有以"Java"開頭的文檔.

—— 掃描所有倒排索引, 性能較差.

GET shop/_search
{
    "query": {
        "prefix": { "name": "java" }
    }
}

3 wildcard query - 通配符檢索

掃描所有倒排索引, 性能較差.

GET shop/_search
{
    "query": {
        "wildcard": { "name": "ja*" }
    }
}

4 regexp query - 正則檢索

掃描所有倒排索引, 性能較差.

GET shop/_search
{
    "query": {
        "regexp": { "name": "jav[a-z]*" }
    }
}

5 fuzzy query - 糾錯檢索

fuzziness的默認值是2 —— 表示最多可以糾錯兩次.

說明: fuzziness的值太大, 將削弱檢索條件的作用, 也就是說糾錯次數太多, 就會導致限定檢索結果的檢索條件被改變, 失去了限定作用.

示例: 檢索name中包含"Java"的文檔, Java中缺失了一個字母a:

GET shop/_search
{
    "query": {
        "match": { 
            "name": {
                "query": "Jav", 
                "fuzziness": 1, 
                "operator": "and"
            }
        }
    }
}

6 boost評分權重 - 控制文檔的優先級別

通過boost參數, 令滿足某個條件的文檔的得分更高, 從而使得其排名更靠前.

GET shop/_search
{
    "query": {
        "bool": {
            "must": [
                { "match": { "name": "編程思想"} }
            ], 
            "should": [
                { 
                   "match": { 
                        "name": {
                            "query": "藝術", 
                            "boost": 2        // 提升評分權重
                        } 
                    }
                }
            ]
        }
    }
}

7 dis_max的用法 - best fields策略

一般檢索中, 檢索條件會被分詞, bool檢索構建多個子檢索 (must | must_not | should | filter), 這些子檢索可能會包含多個field. 這時:

多個子檢索的field各自匹配少量關鍵字的文檔的分數 > 某個子檢索的field匹配大量關鍵字的文檔的分數.

7.1 dis_max的提出

如果我們希望檢索結果中 (檢索串被分詞后的) 關鍵字匹配越多, 這樣的文檔就越靠前, 而不是多個子檢索中匹配少量分詞的文檔靠前.

⇒ 此時可以使用dis_max和tie_breaker.

tie_breaker的值介於0~1之間, Elasticsearch將 bool檢索的分數 * tie_breaker的結果與dis_max的最高分進行比較, 除了取dis_max的最高分以外, 還會考慮其他的檢索結果的分數.

7.2 使用示例

為了增加精准度, 常用的是配合boost、minimum_should_match等參數控制檢索結果.

GET shop/_search
{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "name": "虛擬機" } },
                { "match": { "desc": "經典" } }
            ],
            "tie_breaker": 0.2		// 對同時滿足的文檔的分值進行提升
        }
    }
}

GET shop/_search
{
    "query": {
        "dis_max": {
            "queries": [
                { 
                    "match": { 
                        "name": {
                            "query": "虛擬機",
                            "minimum_should_match": "50%",
                            "boost": 2
                        }
                    }
                },
                {
                    "match": {
                        "desc": {
                            "query": "經典",
                            "minimum_should_match": "50%", 
                            "boost": 3
                        }
                    }
                }
            ],
            "tie_breaker": 0.3
        }
    }
}

8 exist query - 存在檢索, 已過期

這是Elasticsearch 2.x中的API, 后續版本不再支持.

9 復雜檢索的使用范例

9.1 多條件過濾 - 包含

檢索出版時間在2012-07之后, 且至少滿足下述條件中一個的文檔:
a. 名稱(name)中包含"並發";
b. 描述(desc)中包含"java";
c. 出版社(publisher)名稱中不包含"電子".

GET shop/_search
{
    "query": {
        "bool": {
            "filter": {					// 按時間過濾
                "range": {
                    "date": {"gte": "2012-07"}
                }
            },
            "should": [					// 可匹配, 可不匹配
                {
                    "match": { "name": "並發" }
                },
                {
                    "bool": {
                        "must": {		// 必須匹配
                            "match": { "desc": "java" }
                        },
                        "must_not": {	// 不能匹配
                            "match": { "publisher": "電子" }
                        }
                    }
                }
            ],
            "minimum_should_match": 1	// 至少滿足should中的一個條件
        }
    }, 
    // 自定義排序
	"sort": [
        { "price": { "order": "desc" } }
    ]
}

注意: 排序的字段最好是數字, 或日期, 因為字符串字段會被分詞, ES會通過分詞后的某個詞去排序, 結果難以預測.

9.2 多條件拼接 - 包含+范圍+排序

匹配檢索: name中包含"java"卻不包含"虛擬機";
范圍檢索: 價格大於50、小於80;
結果排序: 按照價格升序排序.

GET shop/_search
{
    "query": {
        "bool": {
            "must": {						// 必須匹配
                "match": { "name": "java" }
            }, 
            "must_not": {					// 必須不匹配
                "match": { "name": "虛擬機" }
            },
            "filter": {
                "range": {
                    "price": {
                        "gte": 40,
                        "lte": 80,
                        "boost": 2.0	// 設置得分的權重值(提升值), 默認是1.0
                    }
                }
            }
        }
    }
}

關於范圍檢索的使用, 請參考下篇文章: ES 22 - Elasticsearch對數值或日期類型進行范圍檢索

9.3 定制檢索結果的排序規則

(1) 默認排序規則:

ES默認是按檢索結果的分值(_score)降序排列的.

某些情況下, 可能存在無實際意義的_score, 比如filter時所有_score的值都相同:

GET website/_search
{
    "query": {
        "bool": {
            "filter": {
                "term": {
                    "author_id": 5520	// 此時所有符合條件的_score都為0
                }
            }
        }
    }
}

// 或通過constant_score過濾: 
GET website/_search
{
    "query": {
        "constant_score": {
            "filter": {
                "term": {
                    "author_id": 5520	// 此時所有符合條件的_score都為1
                }
            }
        }
    }
}

(2) 定制排序規則:

GET website/_search
{
    "query": {
        "constant_score": {
            "filter": {
                "term": {
                    "author_id": 5520
                }
            }
        }
    }, 
    "sort": [
        {
            "post_date": { "order": "asc" }
        }
    ]
}

版權聲明

作者: 馬瘦風(https://healchow.com)

出處: 博客園 馬瘦風的博客(https://www.cnblogs.com/shoufeng)

感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂👆] 或 [推薦👍] 吧😜

本文版權歸博主所有, 歡迎轉載, 但 [必須在文章頁面明顯位置標明原文鏈接], 否則博主保留追究相關人員法律責任的權利.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM