天天看點

Search template — Elastic Stack 實戰手冊

Search template — Elastic Stack 實戰手冊
https://developer.aliyun.com/topic/download?id=1295 · 更多精彩内容,請下載下傳閱讀全本《Elastic Stack實戰手冊》 https://developer.aliyun.com/topic/download?id=1295 https://developer.aliyun.com/topic/es100 · 加入創作人行列,一起交流碰撞,參與技術圈年度盛事吧 https://developer.aliyun.com/topic/es100

創作人:駱潇龍

Elasticsearch 允許使用模闆語言 mustache 來預設搜尋邏輯,在實際搜尋時,通過參數中的鍵值,對來替換模闆中的占位符,最終完成搜尋。該方式将搜尋邏輯封閉在 Elasticsearch 中,可以使下遊服務,在不知道具體搜尋邏輯的情況下完成資料檢索。我們以 Kibana 自帶的航班資料

kibana_sample_data_flights

為基礎,以按航班号搜尋為例,簡單介紹搜尋模闆的使用。

第一步,建立 ID 為 testSearchTemplate 的搜尋模闆,語句如下

POST _scripts/testSearchTemplate
{ 
  "script": {
    "lang": "mustache",   #使用 mustache 模闆語言
    "source": {   # 腳本内容
      "query": {    # 搜尋邏輯
        "term": {
          "FlightNum": {
            "value": "{{FlightNum}}"  # 占位符 FlightNum
          }
        }
      }
    }
  }
}           

第二步,傳參搜尋資料,語句如下

GET kibana_sample_data_flights/_search/template
{
  "id": "testSearchTemplate",     # 使用的模闆ID
  "params": {
    "FlightNum": "9HY9SWR"    # 占位符替換的值
  }
}           

以上兩步就是使用模闆搜尋資料,該邏輯等同于下面這個搜尋

GET kibana_sample_data_flights/_search
{
  "query": {
    "term": {
      "FlightNum": {
        "value": "9HY9SWR"
      }
    }
  }
}           

API介紹

下面我們從搜尋模闆的生命周期:建立、檢視、使用、删除來展開介紹模闆搜尋相關 API。

準備

在正式介紹之前,我們先來說一說關于模闆搜尋的幾個預備知識。

首先,如果使用的 Elasticsearch 叢集開啟了安全功能,那麼角色對操作的索引必須要有

read

權限。

其次,搜尋模闆使用的文法是

Mustache

更多的關于該種腳本語言的介紹以及功能請檢視其官方 文檔 : https://mustache.github.io/mustache.5.html

最後,模闆搜尋屬于 Elasticsearch 中 Script 功能的擴充, Script 的限定及用法基本都适用于模闆搜尋。比如,叢集關于 Script 的配置也會影響模闆搜尋,配置項

script.allowed_types

可規範模闆搜尋接受的類型( inline / stored / both ),

script.allowed_contexts

也會限制模闆搜尋可進行的操作。

建立

搜尋模闆的建立與 Elasticsearch 其它腳本的建立一樣,都是發送 1 個

POST

請求即可。

如下所示:

POST _scripts/<templateId>  # 1
{
  "script": {
    "lang": "mustache", # 2
    "source": {   # 3
      "query": {
          "term": {
            "FlightNum": {
              "value": "{{FlightNum}}"  # 可變參數 FlightNum
            }
          }
        }
    }
  }
}           
  1. _scripts/<templateId>

    發送 POST 請求來建立搜尋模闆,其中

    <templateId>

    是你為該模闆設定的 ID,搜尋時會用到該 ID
  2. lang 參數配置的是搜尋模闆使用的腳本語言為

    mustache

  3. source 參數配置的是搜尋模闆的具體内容,該部分的格式參照 Elasticsearch 搜尋的請求 body,需要搜尋時填充的值使用

    mustache

    文法,配置占位符即可,比如本例中的占位符就是

    {{FlightNum}}

檢視

當我們想檢視之前建立的模闆内容,或者驗證某個 ID 的模闆是否存在時,可以向

_scripts/<templateId>

發送 GET 請求來擷取模闆的具體内容。

示例如下:

GET _scripts/<templateId>  # 1
{
  "_id" : "testSearchTemplate",  # 2
  "found" : true,  # 3
  "script" : {   # 4
    "lang" : "mustache", 
    "source" : """{"query":{"term":{"FlightNum":{"value":"{{FlightNum}}"}}}}""", 
    "options" : {  # 5
      "content_type" : "application/json; charset=UTF-8"
    }
  }
}           
  1. 請求的 path 為

    _scripts/<templateId>

    ,其中

    <templateId>

    為你要查詢的模闆 Id,請求類型為 GET
  2. 傳回的 body 中,_id 屬性再次表明此次查詢的模闆 ID,本示例查詢的是之前建立的

    testSearchTemplate

    模闆
  3. found 屬性表明此次查詢是否查到結果,如果模闆 ID 存在則此值為 true,反之為 false
  4. script 就是該搜尋模闆的具體内容與儲存時相同。核心有 lang 屬性表示腳本文法,source 屬性存放腳本具體内容
  5. script 屬性中的 Options 屬性是非必要其它腳本屬性,預設會有 content_type 屬性,該屬性儲存查詢時 http 請求的

    content-type

    ,預設為

    application/json; charset=UTF-8

删除

在一個搜尋模闆完成了它的使命後,我們需要及時删除它,因為 Elasticsearch 預設緩存腳本的資料量是有上限的,删除的方式很簡單,發送一個

DELETE

DELETE _scripts/<templateId>   #1           

<templateId>

為要删除的搜尋模闆的 ID,比如

_scripts/testSearchTemplate

表示的就是删除 ID 為

testSearchTemplate

的搜尋模闆。

使用

搜尋模闆的使用就是在搜尋時,直接發送占位符的值,即可執行預設搜尋語句。由于還是在搜尋的範疇,是以發送請求的 path 是

_search/template

下面是關于使用搜尋模闆進行查詢的示例:

GET <index>/_search/template?<query_parameters> #1
{
  "source": """{"query": {"term": {"FlightNum": {"value": "{{FlightNum}}"}}}}""",  #2
  "id": "testSearchTemplate", # 3
  "params": {  # 4
    "FlightNum": "9HY9SWR"
  },
  "profile": true, # 5
  "explain": true  # 6
}           

模闆搜尋發送的位址為

<index>/_search/template

,與搜尋一樣

<index>

處為選填參數,你可以指定搜尋的索引,不指定則表示搜尋全部索引。

因為本質上還是屬于搜尋的範疇,是以一些搜尋參數在模闆搜尋是也可以使用,比如:

  • scroll(可選,時長):表示本搜尋需要支援遊标搜尋,遊标過期時間為配置值
  • ccs_minimize_roundtrips(可選,布爾值):如果為 true 則在跨叢集搜尋時最小化叢集間互動。預設為 true
  • expand_wildcards(可選,字元串):表示索引通配符作用的範圍,可配置為全部(all)、打開索引(open)、關閉索引(closed)、隐藏索引(hidden,需要與open或closed結合使用)、不允許通配符(none)
  • explain(可選,布爾值):表示傳回結果是否帶計算得分的詳細資訊,預設是false
  • ignore_throttled(可選,布爾值):如果為 true 則表示查詢忽略被限制的索引,被限制的索引一般指被當機(freeze)的索引,該值預設是 true
  • ignore_unavailable(可選,布爾值):如果為 true 則表示關閉的索引不在搜尋範圍内,預設值為 true
  • preference(可選,字元串):指定執行該操作的節點或分片,預設是随機的
  • rest_total_hits_as_int(可選,布爾值):如果為 true 則 hits.total 将會是個數值而非一個對象,預設為 false
  • routing(可選, 字元串):配置搜尋執行的路由
  • search_type(可選,字元串):這是搜尋的類型,可選值有:query_then_fetch、dfs_query_then_fetch
  • source 字段:用于配置搜尋模闆,該字段與 ID 字段沖突隻能二選一,使用 source 表示不使用儲存的模闆而使用本模闆
  • id 字段:表示本次查詢使用的搜尋模闆 ID,該字段與 source 字 段沖突隻能二選一
  • params 字段:配置的 key-value 值将替換模闆中的占位符執行搜尋
  • profile 字段:是可選字段,表示傳回結果中是否有 Elasticsearch 執行搜尋的一些元資訊
  • explain 字段:是可選字段,與 http 中搜尋參數配置的 explain 含義一樣,表示結果是否帶計算得分的詳細資訊

上述搜尋傳回結果如下:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 9.071844,
    "hits" : [
      {
        "_shard" : "[kibana_sample_data_flights][0]",
        "_node" : "ydZx8i8HQBe69T4vbYm30g",
        "_index" : "kibana_sample_data_flights",
        "_type" : "_doc",
        "_id" : "KPRFDHkB9LctWlE3WLqj",
        "_score" : 9.071844,
        "_source" : {
          "FlightNum" : "9HY9SWR",
          "DestCountry" : "AU",
          "OriginWeather" : "Sunny"
        },
        "_explanation" : {}  # 計算得分的邏輯
      }
    ]
  },
  "profile" : {} # 搜尋細節資訊
}           

其它

本部分将介紹關于模闆搜尋的一些小技巧。通常情況下我們寫的搜尋模闆,往往是很難一次就配置正确的,是以需要頻繁的測試我們寫的模闆,與參數結合後是否是我們預期的搜尋語句,這時我們就可以使用以下這個請求,來校驗模闆使用是否正确。

GET _render/template # 1
{
  "source": """{"query": {"term": {"FlightNum": {"value": "{{FlightNum}}"}}}}""" ,# 2
  "params": { # 3
    "FlightNum": "9HY9SWR"
  }
}

{  # 4
  "template_output" : {
    "query" : {
      "term" : {
        "FlightNum" : {
          "value" : "9HY9SWR"
        }
      }
    }
  }
}           
  1. _render/template

    發送 GET 請求來驗證模闆是否正确
  2. source 字段為要驗證的搜尋模闆,該字段可以省略,如果省略需要在 path 處指定模闆iID,比如

    _render/template/testSearchTemplate

  3. params 字段為模闆使用的參數
  4. 此 JSON 就是該請求的傳回,

    template_output

    字段就是在使用此

    params

    下搜尋模闆生成的查詢語句

模闆語言 mustache 有許多功能,這裡再介紹幾個比較常見的。

比如我們使用占位符替換的不是一個字元串,而是一個對象或數組對象,那麼我們可以用

{{#toJson}}{{/toJson}}

來實作,

具體如下:

GET _render/template
{
  "source": """{"query": {"term": {"FlightNum": {{#toJson}}FlightNum{{/toJson}}  }}}""", # 1
  "params": { # 2
    "FlightNum": {
      "value":"9HY9SWR"
    }
  }
}

{ # 3
  "template_output" : {
    "query" : {
      "term" : {
        "FlightNum" : {
          "value" : "9HY9SWR"
        }
      }
    }
  }
}           

在配置模闆時,我們将

FlightNum

的 value 配置為

{{#toJson}}FlightNum{{/toJson}}

,即表示占位符

FlightNum

是一個對象

在配置 params 時,我們将 FlightNum 的值設定為一個 JSON 對象

{ "value":"9HY9SWR"}

通過校驗請求的傳回,可以看到

{{#toJson}}FlightNum{{/toJson}}

被替換為對象

{ "value":"9HY9SWR"}

Mustache 還能在将變量套入模闆時做一些處理,比如将數組變量組合成字元串放入模闆、設定占位符的預設值,以及對 URL 轉碼。

示例如下

GET _render/template
{
  "source": {
    "query": {
      "term": {
        "FlightNum": "{{#join delimiter='||'}}FlightNums{{/join delimiter='||'}}", #1
        "DestCountry":"{{DestCountry}}{{^DestCountry}}AU{{/DestCountry}}",#2
        "Dest": "{{#url}}{{Dest}}{{/url}}"#3
      }
    }
  },
  "params": {
    "FlightNums": [
      "9HY9SWR",
      "adf2c1"
    ],
    "Dest":"http://www.baidu.com"
  }
}

{
  "template_output" : {
    "query" : {
      "term" : {
        "FlightNum" : "9HY9SWR||adf2c1", # 4
        "DestCountry" : "AU", #5
        "Dest" : "http%3A%2F%2Fwww.baidu.com" # 6
      }
    }
  }
}           

第一個模闆使用

{{#join delimiter='||'}}{{/join delimiter='||'}}

設定了數組合并的分割字元為 "||",傳參時

FlightNums

配置的為

["9HY9SWR","adf2c1"]

,而生成的則是 #4 處的

9HY9SWR||adf2c1

第二個模闆使用

{{^DestCountry}}AU{{/DestCountry}}

設定了占位符 DestCountry 的預設值為 AU,這樣我們在params中并未配置 DestCountry 的值,但生成的 #5 處自動用 AU 替換了占位符

第三個模闆我們用

{{#url}}{{/url}}

聲明了此處是一個 URL,需要進行轉義,則在 #6 處配置的

http://www.baidu.com

變為了

http%3A%2F%2Fwww.baidu.com

繼續閱讀