天天看點

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

Painless Lab 是 Elasticsearch 7.13 引入的實驗性功能,是一個互動式代碼編輯器,可以實時測試和調試 Painless 腳本。

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

本文展開解讀 Painless Lab 如何應用于企業級實戰開發中的腳本調試環節!

1、Painless Lab 是什麼?

Painless Lab是一個互動式的測試版代碼編輯器,用于實時測試和調試Painless腳本。

咱們可以通過打開主菜單,點選開發工具,然後選擇 Painless Lab 來通路它。

如下圖所示,左側是:腳本輸入區域。右側由三部分組成:

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?
  • Output:代表結果輸出,确切說是調試結果輸出。
  • Parameters:代表參數輸入。
  • Context:代表上下文,确切說是不同腳本類型選型與選擇。

2、Painless Lab 能幹什麼?

一句話:Painless Lab 可以實時測試和調試 Painless 腳本。

Painless Lab 允許我們建立 Kibana 運作時字段(runtime fields)、處理重新索引的資料(reindex)、定義複雜的 Watcher 條件(付費功能),并在其他上下文中處理資料。

下面的 Context 部分展開就是 Painless Lab 的核心功能區域。

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

三種類型進一步展開:

Elasticsearch實戰 :如何借助 Kibana 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 上下文是最合适的選擇。

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

https://www.elastic.co/guide/en/elasticsearch/reference/current/script-processor.html

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

如上圖所示,我們在 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 所示。

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

上述腳本實作的核心功能就是:以分隔符截斷字元串,形成獨立字元串,插入到 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]
}
           

上述索引必須建構,否則會報錯如下圖所示。

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

錯誤原因可能是:索引不存在或者Mapping 不存在。

正确的執行步驟如下所示:

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

結合上面三個步驟以及左側的腳本,主要驗證左側腳本正确與否。注意:傳回值必須是 Bool 類型。執行結果如下:

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

最終結合上述調試成功的腳本,整合到 script query 檢索語句中,就能得到滿足使用者預期的結果資料。

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?
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
}
           
Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

左側腳本部分

// 擷取參數值
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;
           

執行結果如下所示:

Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

上述腳本通過使用 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"  // 使用腳本計算的分數替換原始分數
    }
  }
}
           
Elasticsearch實戰 :如何借助 Kibana Painless Lab 進行腳本調試?

實作核心:根據自定義邏輯計算分數: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