天天看點

Elasticsearch 7.x 檢索文檔的三種方式:全文搜尋、詞項搜尋、複合搜尋

Elasticsearch 7提供了多種檢索文檔的方式,我們可以通過Restful API的方式來搜尋索引中的文檔。Elasticsearch的搜尋可以分為以下幾個類型:

  • 全文搜尋
  • 詞項搜尋
  • 複合搜尋
  • 嵌套搜尋
  • 位置搜尋
  • 特殊搜尋

本文例子采用測試文檔庫shakespeare,下載下傳連結https://www.elastic.co/guide/en/kibana/7.2/tutorial-build-dashboard.html 。

1 全文搜尋

全文搜尋通常用于搜尋文本字段,需要使用者提供關鍵字來完成。

1.1 match搜尋

match搜尋會對使用者給出的關鍵詞進行解析,首先會将其進行分詞處理,分詞後查詢語句中的任意一個詞項被比對,文檔就會檢索到。其子參數包含:

  • query

    (必填):搜尋關鍵文本
  • analyzer

    (可選):分詞器,用于将

    query

    中的文本轉換為一個個詞項
  • fuzziness

    (可選):使用編輯距離技術進行模糊比對
  • prefix_length

    :模糊比對的起始單詞數
  • operator

    (預設為OR):布爾邏輯,用來解釋

    query

    中的詞項,可選的參數有OR、AND
  • minimum_should_match

    (可選):傳回的文檔需要比對的最小子串數

示例:

GET /shakespeare/_search
{
  "query": {
    "match": {
      "text_entry": {
        "query": "apple eye", 
        "operator": "and"
      }
    }
  }
}
           

查詢包含

text_entry

字段中包含單詞apple和eye的文檔

1.2 match_phrase搜尋

match_phrase搜尋會首先把

query

進行分詞處理,分詞器可以自定義,同時文檔還需滿足以下條件才能被比對:

  • 分詞後所有詞項都要出現在該字段中
  • 字段中所有的詞項順序要一緻

如果将上述示例改為match_phrase,那麼隻有eye在apple後面的文檔才可以被搜尋到。

1.3 match_phrase_prefix搜尋

和match_phrase搜尋類似,隻不過match_phrase_prefix支援詞項的字首比對,例如:

GET /shakespeare/_search
{
  "query": {
    "match_phrase_prefix": {
      "text_entry": {
        "query": "app"
      }
    }
  }
}
           

那麼隻會查找出某個詞項的字首為app的文檔。

1.4 multi_match搜尋

multi_match搜尋是match的更新版,可以用于搜尋多個字段,例如:

GET /shakespeare/_search
{
  "query": {
    "multi_match": {
        "query": "apple",
        "fields": ["text_entry", "speaker"]
    }
  }
}
           

上述查詢語句會在

text_entry

speaker

字段中查詢包含單詞apple的文檔

1.5 match_bool_prefix搜尋

match_bool_prefix搜尋于Elasticsearch 7.0推出,它将輸入的文本通過指定的分詞器來處理多個

term

,然後基于這些

term

進行bool query,除了最後一個

term

使用字首查詢,其它都是使用term_query。

GET /shakespeare/_search
{
  "query": {
    "match_bool_prefix": {
        "query": "away as nim",
    }
  }
}
           

上述示例相當于查詢包含單詞away、as,并且有單詞以nim開頭的文檔。

2 詞項搜尋

全文搜尋在查詢前會分析

query

字元串,而詞項搜尋一般用于對存儲的詞項進行精确搜尋,通常用于一些結構化資料,例如數字、枚舉類型、日期類型等。

2.1 term

最基本的詞項搜尋,用于檢索出某個

text

字段中包含指定單詞的文檔。例如:

GET /shakespeare/_search
{
  "query": {
    "term": {
      "text_entry": {
        "value": "apple",
        "boost": 1.0
      }
    }
  }
}
           

上述請求可以查找出

text_entry

字段中包含單詞apple的文檔。

value

參數為需要查找的詞項;

boost

用來減少或增加相關性系數,預設為1.0,大于1.0會增加其相關性,小于1.0會減少其相關性。

2.2 terms

terms

可以用來查找

text

字段中包含一個或多個指定單詞的文檔,例如:

GET /shakespeare/_search
{
  "query": {
    "terms": {
      "text_entry": [
        "eye","apple"
      ]
    }
  }
}
           

上述請求會查找出

text_entry

字段中滿足以下要求的文檔:

  • 包含單詞eye,不包含單詞apple
  • 包含單詞apple,不包含單詞eye
  • 包含單詞eye和apple

同樣,terms也可以使用

boost

來減少或增加相關性系數。

2.3 regexp

regexp

檢索可以查找出包含滿足正規表達式單詞的文檔,例如:

GET /shakespeare/_search
{
  "query": {
    "regexp": {
      "text_entry": "pa.*"
    }
  }
}
           

上述請求會查找出

text_entry

字段中包含以pa開頭的單詞的文檔。

需要注意

regexp

檢索不支援包含

^

(行的開頭)或

$

(行的結尾)的正規表達式。

regexp

檢索還支援以下幾個參數:

  • flags

    :啟用正規表達式可選運算符
  • max_determinized_states

    :查詢所需的最大自動機狀态數,用于限制過于複雜的正規表達式,預設10000。
2.4 prefix

prefix

檢索可以查找出包含指定字元串開頭的單詞的文檔,例如:

GET /shakespeare/_search
{
  "query": {
    "prefix": {
      "text_entry": {
        "value": "par"
      }
    }
  }
}
           

上述請求會查找出包含以par開頭的單詞的文檔。

2.5 range

range

檢索可以用于查詢指定字段中在指定範圍内的文檔,例如:

GET /shakespeare/_search
{
  "query": {
    "range": {
      "line_id": {
        "gte": 160,
        "lte": 170
      }
    }
  }
}
           

上述請求可以查找出

line_id

字段大于等于160,小于等于170的文檔。此外還有

gt

lt

,用于表示大于和小于符号。

2.6 wildcard

wildcard

檢索用于單詞的通配符檢索,相當于一個簡化版本的

regexp

檢索,

?

用于比對一個任意字元,

*

号用于比對0個或者多個任意字元,相當于正則的

.*

。例如:

GET /shakespeare/_search
{
  "query": {
    "wildcard": {
      "text_entry": {
        "value": "pre*"
      }
    }
  }
}
           

上述請求可以查找出

text_entry

字段中包含以pre開頭的單詞的文檔。此外

wildcard

也支援

boost

參數,作用類似。

2.7 fuzzy

fuzzy

檢索用于詞項的近似檢索,例如

applx

可以檢索出包含

apple

單詞的文檔,兩個單詞的相似度通過編輯距離算法(Levenshtein)确定。例如:

GET /shakespeare/_search
{
  "query": {
    "fuzzy": {
      "text_entry": "applx"
    }
  }
}
           

上述請求可以查找出包含近似applx單詞的文檔,例如包含apple、apply的文檔等。

fuzzy

查詢效率不高,需要消耗的資源比較大。

3 複合查詢

複合查詢就是将一些簡單的查詢組合在一起作為查詢條件進行文檔檢索。

3.1 constant_score

constant_score

檢索可以包裝一個其它類型的查詢,并傳回比對過濾器中的查詢條件且具備相同評分的文檔。

GET /shakespeare/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "text_entry": "apple"
        }
      },
      "boost": 1.2
    }
  }
}
           

上述查詢條件會傳回包含apple單詞的文檔,并且評分都是1.2

3.2 bool

bool

查詢可以将任意多個簡單查詢組合在一起,使用

must

should

must_not

filter

選項來表示簡單查詢之間的邏輯:

  • must

    :文檔必須要比對

    must

    下的查詢條件
  • should

    :文檔可以比對也可以不比對

    should

    下的查詢條件,比對的文檔評分會更高
  • must_not

    :比對該選項下的查詢條件的文檔會被過濾,不會傳回
  • filter

    :和

    must

    類似,不同的是

    filter

    中的條件不會參與評分。

例如:

GET /shakespeare/_search
{
  "query": {
    "bool": {
      "must": [{
        "term": {
          "text_entry": {
            "value": "must"
          }
        }}
      ],
      
      "should": [{
        "term": {
          "text_entry": {
            "value": "have"
          }
        }}
      ]
    }
  }
}
           

注意

must

should

must_not

filter

的值都是JSON數組,可以添加多個查詢條件,包括詞項搜尋和全文搜尋。

3.3 function_score

function_score

可以修改查詢的文檔的得分,使用者需要定義一個查詢和一到多個評分函數,評分函數會對查詢到的每個文檔分别計算其得分。

例如:

GET /shakespeare/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "text_entry": "apple"
        }
      },
      "script_score": {
        "script": {
          "inline": "Math.sqrt(doc['line_id'].value)"
        }
      }
    }
  }
}
           

上述請求可以查找出

text_entry

包含apple的文檔,并且評分按照

line_id

的開方計算。

function_score

查詢方式内嵌了多種函數和查詢方法,可以參照官方文檔了解更多。

3.4 dis_max

dis_max

檢索(Disjucation Max Query)和

bool

檢索有聯系也有差別,

dis_max

支援多并發查詢,可以傳回與任意查詢條件子句比對的任何文檔類型。和

bool

檢索不同的是,

dis_max

查詢隻使用最佳比對查詢條件的分數:

GET /shakespeare/_search
{
  "query": {
    "dis_max": {
      "tie_breaker": 0.7,
      "boost": 1.2,
      "queries": [
        { "term": { "text_entry": "apple" } },
        { "term": { "text_entry": "watch" } }
      ]
    }
  }
}
           
3.5 boosting

boosting查詢适用于需要對評分進行調整的場景,它會把兩個查詢封裝在一起并降低其中一個查詢條件的評分,例如:

GET /shakespeare/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "text_entry": "apple"
        }
      },
      "negative": {
        "range": {
          "line_id": {
            "gte": 0,
            "lte": 10000
          }
        }
      },
      "negative_boost": 0.2
    }
  }
}
           

上述查詢條件中會降低

line_id

在0到10000之間的文檔的評分,會降低到原先的0.2倍。

繼續閱讀