1. 程式人生 > 其它 >DSL查詢ES文件

DSL查詢ES文件

1.DSL查詢分類

Elasticsearch提供了基於JSON的DSL(Domain Specific Language)來定義查詢。常見的查詢型別包括:

  • 查詢所有:查詢出所有資料,一般測試用。例如:match_all

  • 全文檢索(full text)查詢:利用分詞器對使用者輸入內容分詞,然後去倒排索引庫中匹配。例如:

    • match_query

    • multi_match_query

  • 精確查詢:根據精確詞條值查詢資料,一般是查詢keyword、數值、日期、boolean等型別欄位。例如:

    • ids

    • range

    • term

  • 地理(geo)查詢:根據經緯度查詢。例如:

    • geo_distance

    • geo_bounding_box

  • 複合(compound)查詢:複合查詢可以將上述各種查詢條件組合起來,合併查詢條件。例如:

    • bool

    • function_score

查詢的語法基本一致:

GET/{索引名稱}/_search
{
"query":{
"查詢型別":{
"查詢條件":"條件值"
}
}
}

  

我們以查詢所有為例,其中:

  • 查詢型別為match_all

  • 沒有查詢條件

// 查詢所有
GET/indexName/_search
{
"query":{
"match_all":{
    }
}
}

  其它查詢無非就是查詢型別

查詢條件的變化。

2.全文檢索查詢

使用場景

全文檢索查詢的基本流程如下:

  • 對使用者搜尋的內容做分詞,得到詞條

  • 根據詞條去倒排索引庫中匹配,得到文件id

  • 根據文件id找到文件,返回給使用者

比較常用的場景包括:

  • 商城的輸入框搜尋

  • 百度輸入框搜尋

基本語法

常見的全文檢索查詢包括:

  • match查詢:單欄位查詢

  • multi_match查詢:多欄位查詢,任意一個欄位符合條件就算符合查詢條件

match查詢語法如下:

GET/indexName/_search
{
"query":{
"match":{
"FIELD":"TEXT"
}
}
}

  

mulit_match語法如下:

GET/indexName/_search
{
"query":{
"multi_match":{
"query":"TEXT",
"fields":["FIELD1"," FIELD12"]
}
}
}

  

match查詢示例:

multi_match查詢示例:

可以看到,兩種查詢結果是一樣的,為什麼?

因為我們將brand、name、business值都利用copy_to複製到了all欄位中。因此你根據三個欄位搜尋,和根據all欄位搜尋效果當然一樣了。

但是,搜尋欄位越多,對查詢效能影響越大,因此建議採用copy_to,然後單欄位查詢的方式。

match和multi_match的區別是什麼?

  • match:根據一個欄位查詢

  • multi_match:根據多個欄位查詢,參與查詢欄位越多,查詢效能越差

3.精準查詢

精確查詢一般是查詢keyword、數值、日期、boolean等型別欄位。所以不會對搜尋條件分詞。常見的有:

  • term:根據詞條精確值查詢

  • range:根據值的範圍查詢

term查詢

因為精確查詢的欄位搜是不分詞的欄位,因此查詢的條件也必須是不分詞的詞條。查詢時,使用者輸入的內容跟自動值完全匹配時才認為符合條件。如果使用者輸入的內容過多,反而搜尋不到資料。

語法說明:

//term查詢
GET/indexName/_search
{
"query":{
"term":{
"FIELD":{
"value":"VALUE"
}
}
}
}

  

當我搜索的是精確詞條時,能正確查詢出結果:

但是,當我搜索的內容不是詞條,而是多個詞語形成的短語時,反而搜尋不到:

range查詢

範圍查詢,一般應用在對數值型別做範圍過濾的時候。比如做價格範圍過濾。

基本語法:

//range查詢
GET/indexName/_search
{
"query":{
"range":{
"FIELD":{
"gte":10, // 這裡的gte代表大於等於,gt則代表大於
"lte":20 // lte代表小於等於,lt則代表小於
}
}
}
}

示例:

總結

精確查詢常見的有哪些?

  • term查詢:根據詞條精確匹配,一般搜尋keyword型別、數值型別、布林型別、日期型別欄位

  • range查詢:根據數值範圍查詢,可以是數值、日期的範圍

4.地理座標查詢

所謂的地理座標查詢,其實就是根據經緯度查詢,官方文件:https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-queries.html

矩形範圍查詢,也就是geo_bounding_box查詢,查詢座標落在某個矩形範圍的所有文件:

查詢時,需要指定矩形的左上右下兩個點的座標,然後畫出一個矩形,落在該矩形內的都是符合條件的點。

語法如下:

//geo_bounding_box查詢
GET/indexName/_search
{
"query":{
"geo_bounding_box":{
"FIELD":{
"top_left":{ // 左上點
"lat":31.1,
"lon":121.5
},
"bottom_right":{ // 右下點
"lat":30.9,
"lon":121.7
}
}
}
}
}

  

附近查詢

附近查詢,也叫做距離查詢(geo_distance):查詢到指定中心點小於某個距離值的所有文件。

換句話來說,在地圖上找一個點作為圓心,以指定距離為半徑,畫一個圓,落在圓內的座標都算符合條件:

語法說明:

//geo_distance 查詢
GET/indexName/_search
{
"query":{
"geo_distance":{
"distance":"15km", // 半徑
"FIELD":"31.21,121.5" // 圓心
}
}
}

  

示例:

我們先搜尋陸家嘴附近15km的酒店:

發現共有47家酒店。

然後把半徑縮短到3公里:

可以發現,搜尋到的酒店數量減少到了5家。

5.複合查詢

複合(compound)查詢:複合查詢可以將其它簡單查詢組合起來,實現更復雜的搜尋邏輯。常見的有兩種:

  • fuction score:算分函式查詢,可以控制文件相關性算分,控制文件排名

  • bool query:布林查詢,利用邏輯關係組合多個其它的查詢,實現複雜搜尋

算分函式查詢

根據相關度打分是比較合理的需求,但合理的不一定是產品經理需要的。

以百度為例,你搜索的結果中,並不是相關度越高排名越靠前,而是誰掏的錢多排名就越靠前。

要想認為控制相關性算分,就需要利用elasticsearch中的function score 查詢了。

1)語法說明

function score 查詢中包含四部分內容:

  • 原始查詢條件:query部分,基於這個條件搜尋文件,並且基於BM25演算法給文件打分,原始算分(query score)

  • 過濾條件:filter部分,符合該條件的文件才會重新算分

  • 算分函式:符合filter條件的文件要根據這個函式做運算,得到的函式算分(function score),有四種函式

    • weight:函式結果是常量

    • field_value_factor:以文件中的某個欄位值作為函式結果

    • random_score:以隨機數作為函式結果

    • script_score:自定義算分函式演算法

  • 運算模式:算分函式的結果、原始查詢的相關性算分,兩者之間的運算方式,包括:

    • multiply:相乘

    • replace:用function score替換query score

    • 其它,例如:sum、avg、max、min

function score的執行流程如下:

  • 1)根據原始條件查詢搜尋文件,並且計算相關性算分,稱為原始算分(query score)

  • 2)根據過濾條件,過濾文件

  • 3)符合過濾條件的文件,基於算分函式運算,得到函式算分(function score)

  • 4)將原始算分(query score)和函式算分(function score)基於運算模式做運算,得到最終結果,作為相關性算分。

因此,其中的關鍵點是:

  • 過濾條件:決定哪些文件的算分被修改

  • 算分函式:決定函式算分的演算法

  • 運算模式:決定最終算分結果

2)示例

需求:給“如家”這個品牌的酒店排名靠前一些

翻譯一下這個需求,轉換為之前說的四個要點:

  • 原始條件:不確定,可以任意變化

  • 過濾條件:brand = "如家"

  • 算分函式:可以簡單粗暴,直接給固定的算分結果,weight

  • 運算模式:比如求和

因此最終的DSL語句如下:

GET/hotel/_search
{
"query":{
"function_score":{
"query":{  .... }, // 原始查詢,可以是任意條件
"functions":[//算分函式
{
"filter":{//滿足的條件,品牌必須是如家
"term":{
"brand":"如家"
}
},
"weight":2//算分權重為2
}
],
      "boost_mode": "sum" // 加權模式,求和
}
}
}

  測試,在未新增算分函式時,如家得分如下:

添加了算分函式後,如家得分就提升了:

3)小結

function score query定義的三要素是什麼?

  • 過濾條件:哪些文件要加分

  • 算分函式:如何計算function score

  • 加權方式:function score 與 query score如何運算