Painless Lab 是 Elasticsearch 7.13 引入的實驗性功能,是一個互動式代碼編輯器,可以實時測試和調試 Painless 腳本。
本文展開解讀 Painless Lab 如何應用于企業級實戰開發中的腳本調試環節!
1、Painless Lab 是什麼?
Painless Lab是一個互動式的測試版代碼編輯器,用于實時測試和調試Painless腳本。
咱們可以通過打開主菜單,點選開發工具,然後選擇 Painless Lab 來通路它。
如下圖所示,左側是:腳本輸入區域。右側由三部分組成:
- Output:代表結果輸出,确切說是調試結果輸出。
- Parameters:代表參數輸入。
- Context:代表上下文,确切說是不同腳本類型選型與選擇。
2、Painless Lab 能幹什麼?
一句話:Painless Lab 可以實時測試和調試 Painless 腳本。
Painless Lab 允許我們建立 Kibana 運作時字段(runtime fields)、處理重新索引的資料(reindex)、定義複雜的 Watcher 條件(付費功能),并在其他上下文中處理資料。
下面的 Context 部分展開就是 Painless Lab 的核心功能區域。
三種類型進一步展開:
進一步再展開解讀。
https://www.elastic.co/guide/en/elasticsearch/painless/8.11/painless-execute-api.html#_contexts
上下文描述painless_test預設上下文,如果沒有指定其他上下文則使用此上下文。用于通用腳本測試,例如調試和驗證腳本邏輯。filter将腳本視為在腳本查詢中運作。用于過濾資料。score将腳本視為在 function_score 查詢中的 script_score 函數中運作。用于評分資料。
2.1 painless_test 類型
預設上下文,如果沒有指定其他上下文則使用此上下文。用于通用腳本測試,例如調試和驗證腳本邏輯。
2.2 filter 類型
将腳本視為在腳本查詢中運作。用于過濾資料。
2.3 score 類型
将腳本視為在 function_score 查詢中的 script_score 函數中運作。用于評分資料。
我們逐一詳盡展開解讀,確定大家跟着過一遍,就能學得會!
3、 Basic painless_test 基礎調試
Basic 上下文允許我們獨立測試腳本邏輯,并将結果轉換為字元串輸出。
樣例資料可以放到 params 中作為輸入。
實戰舉例如下:
對于 Ingest pipeline 腳本,參考官方示例,由于腳本是在 Ingest Pipeline 中處理資料的,并且沒有涉及到查詢過濾 filter 或評分 score,是以 Basic 上下文是最合适的選擇。
https://www.elastic.co/guide/en/elasticsearch/reference/current/script-processor.html
如上圖所示,我們在 parameters 中輸入如下資料:
{
"ctx": {
"env": "小米-筆記本-電腦-雷軍"
},
"params": {
"delimiter": "-",
"position": 1
}
}
我們在左側輸入如下的 painless script 腳本,如下所示:
// 擷取 ctx 資料
def ctx = params.ctx;
// 擷取參數
def delimiter = params.params.delimiter;
def position = params.params.position;
// 執行腳本邏輯
String[] envSplit = ctx.env.splitOnToken(delimiter);
ArrayList tags = new ArrayList();
//tags.add(envSplit[position].trim());
for (def tag : envSplit) {
tags.add(tag.trim());
}
ctx.tags = tags;
// 傳回結果以供調試
return ctx.tags;
執行結果如下圖右側 Output 所示。
上述腳本實作的核心功能就是:以分隔符截斷字元串,形成獨立字元串,插入到 tags 集合中。
這樣調試過之後,再微調一下就可以應用到 ingest pipeline 中。
4、filter 過濾調試
差別于剛才的邏輯,這裡需要我們先建立索引,然後基于我們構造的索引資料進行展開 filter 過濾檢索。
POST /hockey/_doc/1
{
"first": "johnny",
"last": "gaudreau",
"goals": [9, 27, 1],
"assists": [17, 46, 0],
"gp": [26, 82, 1]
}
POST /hockey/_doc/2
{
"first": "john",
"last": "doe",
"goals": [2, 3, 4],
"assists": [1, 2, 3],
"gp": [4, 5, 6]
}
上述索引必須建構,否則會報錯如下圖所示。
錯誤原因可能是:索引不存在或者Mapping 不存在。
正确的執行步驟如下所示:
結合上面三個步驟以及左側的腳本,主要驗證左側腳本正确與否。注意:傳回值必須是 Bool 類型。執行結果如下:
最終結合上述調試成功的腳本,整合到 script query 檢索語句中,就能得到滿足使用者預期的結果資料。
POST /hockey/_search
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"lang": "painless",
"source": """
// 擷取 goals 字段的值
def goals = doc['goals'];
// 初始化總和變量
int sum = 0;
// 周遊 goals 數組并計算總和
for (int i = 0; i < goals.size(); i++) {
sum += goals.get(i);
}
// 輸出調試資訊
//Debug.explain(sum);
// 傳回 true 以比對所有文檔,僅用于調試目的
return sum>10;
"""
}
}
}
}
}
}
5、評分 score 類型調試
在 Elasticsearch 中,score 類型調試上下文用于在 function_score 查詢中的 script_score 函數中運作腳本。
該方式允許使用者編寫腳本來動态計算文檔的評分,進而影響搜尋結果的排序。
5.1 真實企業場景再現
假設我們有一個包含産品資訊的索引 products,每個文檔包含以下字段:
- 1.name: 産品名稱
- 2.price: 産品價格
- 3.rating: 産品評分
我們希望根據價格和評分來動态計算每個産品的分數,具體規則如下:
- 1.價格越低,分數越高
- 2.評分越高,分數越高
POST /products/_doc/1
{
"name": "Product A",
"price": 100,
"rating": 4.5
}
POST /products/_doc/2
{
"name": "Product B",
"price": 200,
"rating": 4.0
}
POST /products/_doc/3
{
"name": "Product C",
"price": 150,
"rating": 3.5
}
5.2 評分查詢腳本調試示例
我們将編寫一個 function_score 查詢,使用 Painless 腳本來計算每個文檔的分數,并根據計算結果排序。
核心邏輯:
- 1、擷取字段值;
- 2、腳本重新計算評分;
- 3、傳回自定義評分。
在 Painless Lab 中,可以使用類似的腳本來調試和驗證評分邏輯:
- 構造參數 Parameters 部分
{
"price": 100,
"rating": 4.5
}
左側腳本部分
// 擷取參數值
long price = params.price;
double rating = params.rating;
// 檢查字段值是否存在
if (price == 0 || rating == 0) {
// 如果任一字段值為 0,則傳回預設分數(例如 0)
return 0.0;
}
// 自定義評分邏輯
double score = (1 / (float)price) * rating;
// 傳回評分結果
return score;
執行結果如下所示:
上述腳本通過使用 score 上下文中的 script_score 函數,可以根據自定義邏輯動态計算文檔的分數,進而影響搜尋結果的排序。
這在需要根據複雜規則排序搜尋結果時非常有用。
通過在 Painless Lab 中調試和驗證上述腳本,可以確定評分邏輯的正确性和有效性。
進而,可以組合寫出如下的評分腳本檢索語句。
POST /products/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"script_score": {
"script": {
"source": """
long price = doc['price'].value;
double rating = doc['rating'].value;
// 自定義評分邏輯
double score = (1 / (float)price) * rating;
return score;
"""
}
},
"boost_mode": "replace" // 使用腳本計算的分數替換原始分數
}
}
}
實作核心:根據自定義邏輯計算分數:score = (1 / price) * rating。價格越低,評分越高,分數越高。
boost_mode: 設定為 replace,使用腳本計算的分數替換原始分數。
6、小結
Kibana Painless Lab 是 Elasticsearch 7.13 引入的實驗性功能,為開發者提供互動式代碼編輯器,用于實時測試和調試 Painless 腳本。
通過 painless_test、filter 和 score 上下文三種測試方式,開發者可以建立和調試 Kibana 運作時字段、處理重新索引的資料、定義複雜的 Watcher 條件,并根據複雜規則動态計算文檔分數,提高腳本開發和優化效率。
作者:銘毅天下
來源-微信公衆号:銘毅天下Elasticsearch
出處:https://mp.weixin.qq.com/s/x9FrVCyrmpvJsc7pNGBm2g