(五)elasticsearch之查詢(Query DSL)

elasticsearch之查詢(Query DSL)

一、字段類查詢

字段類查詢主要包含以下2類:

  • 全文匹配:針對text 類型的字段進行全文檢索,會對查詢語句先進行分詞處理,如match、match_phrase等query類型
  • 單詞匹配:不會對查詢語句進行分詞處理,直接去匹配字段的倒排索引,如term、terms、range等query 類型

補:match、match_phase、term、query_string的區別

1.term結構化字段查詢,匹配一個值,且輸入的值不會被分詞器分詞。

比如查詢條件是:

{
    "query":{
        "term":{
            "foo": "hello world"
        }
    }
}

那麼只有在字段中存儲了“hello world”的數據纔會被返回,如果在存儲時,使用了分詞,原有的文本“I say hello world”會被分詞進行存儲,不會存在“hello world”這整個詞,那麼不會返回任何值。

但是如果使用“hello”作爲查詢條件,則只要數據中包含“hello”的數據都會被返回,分詞對這個查詢影響較大。

2.match_phase習語匹配,查詢確切的phase,在對查詢字段定義了分詞器的情況下,會使用分詞器對輸入進行分詞,然後返回滿足下述兩個條件的document:

1.match_phase中的所有term都出現在待查詢字段之中

2.待查詢字段之中的所有term都必須和match_phase具有相同的順序

{ "foo":"I just said hello world" }

{ "foo":"Hello world" }

{ "foo":"World Hello" }

​ 3.使用match_phase:

{
  "query": {
    "match_phrase": {
      "foo": "Hello World"
    }
  }
}

會返回前兩條文檔。

注:slop 參數

通過 slop 參數可以控制單詞間的間隔,如設置"slop": “2”,則表示單詞間可以隔2個單詞。

3.match模糊匹配,先對輸入進行分詞,對分詞後的結果進行查詢,文檔只要包含match查詢條件的一部分就會被返回。

4.query_string語法查詢,同match_phase的相同點在於,輸入的查詢條件會被分詞,但是不同之處在與文檔中的數據可以不用和query_string中的查詢條件有相同的順序。

5.match之 operator參數

通過 operator 參數可以 控制 單詞間的匹配關係,可選項是 or 和 and。

因此,當你希望match 實現 分詞 但詞語必須都包含的情況時,可以修改此參數來達到目的,如下:

GET testindex/_search
{
    "query": {
        "match": {
            "name"{
                "query": "hello world",
                "operator": "and"
            }
        }
    }
}

6.match 之 minimum_should_match 參數

通過minimum_should_match 參數可以控制需要匹配的單詞數。

例:

// 任意滿足其中2個單詞即可
GET testindex/_search
{
    "query": {
        "match": {
            "name": {
                "query": "i want to say hello",
                "minimum_should_match": "2"
            }
        }
    }
}

二、相關性算分

1、介紹

  • 相關係算分是指文檔與查詢語句之間的相關度。
  • 本質是一個排序問題,排序的依據是相關性算分。

2、相關概念

  • Term Frequency(TF)詞頻,即單詞在該文檔中出現的次數。詞頻越高,相關度越大;
  • Document Frequency(DF)文檔頻率,即單詞出現的文檔數;
  • Inverse Document Frequency(IDF)逆向文檔頻率,與 DF 相反,簡單理解是1/DF。即單詞出現的文檔數越少,相關度越大;
  • Filed-length Norm 文檔越短,相關性越大。

3、es 的主要相關性算分模型

  • TF/IDF 模型
  • BM25 模型,5.x之後的默認模型

4、explain 參數(請聯想下explain在mysql的作用)

可以通過explain 參數來查看具體的計算方法,但需要主要以下幾點:

  • es 的算分是按照shard 進行的,即 shard 的分數計算是相互獨立的,所以在使用 explain的時候注意分片數
  • 可以通過設置索引的分片數爲 1來避免這個問題

例:

GET testindex/_search
{
    "explain": true,
    "query": {
        "match": {
            "name": "kate"
        }
    }
}
// 設置shards分片數
PUT testindex
{
	"settings": {
    	"index": {
    		"number_of_shards": "1"
    	}
	}
}

三、複雜查詢之 constant_score 查詢

  • 該查詢將其內部的查詢結果文檔得分都設定爲1 或者boost 的值;
  • 常用於 結合 bool 查詢實現自定義得分。

語法如下:

GET testindex/_search
{
    "query": {
        "constant_score": {
            "filter": {					// 只能有一個
                "match": {
                    "name": "kate"
                }
            }
        }
    }
}

四、複雜查詢之 bool 查詢

bool 查詢可由一個或多個布爾子句組成,主要包含如下4類:

filter 只過濾符合條件的文檔,不計算相關性得分
must 文檔必須符合 must中的所有條件,會影響相關性得分
must_not 文檔必須不符合 must_not 中的所有條件,不計算相關性得分
should 文檔可以符合 should 中的所有條件,會影響相關性得分

1、filter

  • filter 查詢只過濾符合條件的文檔,不計算相關性得分
  • es針對 filter 會有智能緩存,因此其執行效率很高
  • 做簡單匹配查詢且不考慮算分時,推薦使用 filter 替代 query 等

語法如下:

GET testindex/_search
{
    "query": {
        "bool": {
            "filter": [
            	{
                    "term": {
                        "name": "kate"
                    }
            	}
            ]
        }
    }
}

2、should

should 使用分爲2種情況:

(1)bool 查詢只包含 should,不包含must查詢

此時,文檔滿足一個條件即可。

可通過minimum_should_match 來控制滿足條件的個數。

(2)bool 查詢同時包含 should 和 must查詢

此時,文檔必須滿足must 的條件,should可以不滿足,但是如果滿足了should 條件,會增加相關性得分。

五、其他 api

1、_count

統計文檔數目

2、_source

過濾返回結果中 _source 中的字段,主要有以下幾種用法

用法一:
GET testindex/_search?_source=name
用法二:
GET testindex/_search
{
    "_source": false
}
用法三:
GET testindex/_search
{
    "_source": ["name","age"]
}
用法四:
GET testindex/_search
{
    "_source": {
        "includes": "name",
        "excludes": "age"
    }
}

六、常見的查詢問題

1、查詢字段是否存在

GET testindex/_search
{
	"query": {
		"exists": {							// 關鍵字
        	"field": "price"				// price 字段
         }
	}
}

2、查詢空字符串的字段(字段存在,內容是空字符串)

// 利用 wildcardQuery 和 mustNot搭配,可以查到空字符串內容的值
BoolQueryBuilder mustNot = QueryBuilders.boolQuery()
                        .must(QueryBuilders.existsQuery("group_name"))
                        .mustNot(QueryBuilders.wildcardQuery("group_name", "*"));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章