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", "*"));