当前位置:   article > 正文

Elasticsearch 企业级实战 02:如何借助 Kibana Painless Lab 进行脚本调试?

Elasticsearch 企业级实战 02:如何借助 Kibana Painless Lab 进行脚本调试?

上一回

Painless Lab 是 Elasticsearch 7.13 引入的实验性功能,是一个交互式代码编辑器,可以实时测试和调试 Painless 脚本

5a7f43d46e5f52559460397114229fb3.png

本文展开解读 Painless Lab 如何应用于企业级实战开发中的脚本调试环节!

1、Painless Lab 是什么?

Painless Lab是一个交互式的测试版代码编辑器,用于实时测试和调试Painless脚本。

咱们可以通过打开主菜单,点击开发工具,然后选择 Painless Lab 来访问它。

如下图所示,左侧是:脚本输入区域。右侧由三部分组成:

a43009022ab295992b9e424cd7d7f60b.png

  • Output:代表结果输出,确切说是调试结果输出。

  • Parameters:代表参数输入。

  • Context:代表上下文,确切说是不同脚本类型选型与选择。

2、Painless Lab 能干什么?

一句话:Painless Lab 可以实时测试和调试 Painless 脚本。

Painless Lab 允许我们创建 Kibana 运行时字段(runtime fields)、处理重新索引的数据(reindex)、定义复杂的 Watcher 条件(付费功能),并在其他上下文中处理数据。

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

8c808a2b4364f33b3cf5ffc2daf8c899.png

三种类型进一步展开:

e64a3923c4baf18cc97fa59d602e54b9.png

进一步再展开解读。

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 上下文是最合适的选择。

610b52814fd46e772148271742984a97.png

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

371d60f30ebcc6de1cea6937fda53856.png

如上图所示,我们在 parameters 中输入如下数据:

  1. {
  2.   "ctx": {
  3.     "env""小米-笔记本-电脑-雷军"
  4.   },
  5.   "params": {
  6.     "delimiter""-",
  7.     "position"1
  8.   }
  9. }

我们在左侧输入如下的 painless script 脚本,如下所示:

  1. // 获取 ctx 数据
  2. def ctx = params.ctx;
  3. // 获取参数
  4. def delimiter = params.params.delimiter;
  5. def position = params.params.position;
  6. // 执行脚本逻辑
  7. String[] envSplit = ctx.env.splitOnToken(delimiter);
  8. ArrayList tags = new ArrayList();
  9. //tags.add(envSplit[position].trim());
  10. for (def tag : envSplit) {
  11.    tags.add(tag.trim());
  12. }
  13. ctx.tags = tags;
  14. // 返回结果以供调试
  15. return ctx.tags;

执行结果如下图右侧 Output 所示。

d079ab39d963108670bbd6fa1f146b16.png

上述脚本实现的核心功能就是:以分隔符截断字符串,形成独立字符串,插入到 tags 集合中。

这样调试过之后,再微调一下就可以应用到 ingest pipeline 中。

4、filter 过滤调试

区别于刚才的逻辑,这里需要我们先创建索引,然后基于我们构造的索引数据进行展开 filter 过滤检索。

  1. POST /hockey/_doc/1
  2. {
  3.   "first""johnny",
  4.   "last""gaudreau",
  5.   "goals": [9271],
  6.   "assists": [17460],
  7.   "gp": [26821]
  8. }
  9. POST /hockey/_doc/2
  10. {
  11.   "first""john",
  12.   "last""doe",
  13.   "goals": [234],
  14.   "assists": [123],
  15.   "gp": [456]
  16. }

上述索引必须构建,否则会报错如下图所示。

5dc8c3ef5e633efd123029aeea7deb13.png

错误原因可能是:索引不存在或者Mapping 不存在。

正确的执行步骤如下所示:

8d2e72d18cfae94643e12394151f5564.png

结合上面三个步骤以及左侧的脚本,主要验证左侧脚本正确与否。注意:返回值必须是 Bool 类型。执行结果如下:

1123243c02ff895fda24b3b44df1a739.png

最终结合上述调试成功的脚本,整合到 script query 检索语句中,就能得到满足用户预期的结果数据。

6cc0bb62d1491eb1af09efce8206ad43.png

  1. POST /hockey/_search
  2. {
  3.   "query": {
  4.     "bool": {
  5.       "filter": {
  6.         "script": {
  7.           "script": {
  8.             "lang""painless",
  9.             "source""""
  10.             // 获取 goals 字段的值
  11.             def goals = doc['goals'];
  12.             
  13.             // 初始化总和变量
  14.             int sum = 0;
  15.             
  16.             // 遍历 goals 数组并计算总和
  17.             for (int i = 0; i < goals.size(); i++) {
  18.               sum += goals.get(i);
  19.             }
  20.             
  21.             // 输出调试信息
  22.             //Debug.explain(sum);
  23.             
  24.             // 返回 true 以匹配所有文档,仅用于调试目的
  25.             return sum>10;
  26.             """
  27.           }
  28.         }
  29.       }
  30.     }
  31.   }
  32. }

5、评分 score 类型调试

在 Elasticsearch 中,score 类型调试上下文用于在 function_score 查询中的 script_score 函数中运行脚本。

该方式允许用户编写脚本来动态计算文档的评分,从而影响搜索结果的排序。

5.1 真实企业场景再现

假设我们有一个包含产品信息的索引 products,每个文档包含以下字段:

  • 1.name: 产品名称

  • 2.price: 产品价格

  • 3.rating: 产品评分

我们希望根据价格和评分来动态计算每个产品的分数,具体规则如下:

  • 1.价格越低,分数越高

  • 2.评分越高,分数越高

  1. POST /products/_doc/1
  2. {
  3.   "name""Product A",
  4.   "price"100,
  5.   "rating"4.5
  6. }
  7. POST /products/_doc/2
  8. {
  9.   "name""Product B",
  10.   "price"200,
  11.   "rating"4.0
  12. }
  13. POST /products/_doc/3
  14. {
  15.   "name""Product C",
  16.   "price"150,
  17.   "rating"3.5
  18. }

5.2 评分查询脚本调试示例

我们将编写一个 function_score 查询,使用 Painless 脚本来计算每个文档的分数,并根据计算结果排序。

核心逻辑:

  • 1、获取字段值;

  • 2、脚本重新计算评分;

  • 3、返回自定义评分。

在 Painless Lab 中,可以使用类似的脚本来调试和验证评分逻辑:

  • 构造参数 Parameters 部分

  1. {
  2.     "price"100,
  3.     "rating"4.5
  4. }

825195d6dc5dd984e1d8b0da3ba91f5a.png

左侧脚本部分

  1. // 获取参数值
  2. long price = params.price;
  3. double rating = params.rating;
  4. // 检查字段值是否存在
  5. if (price == 0 || rating == 0) {
  6.     // 如果任一字段值为 0,则返回默认分数(例如 0)
  7.     return 0.0;
  8. }
  9. // 自定义评分逻辑
  10. double score = (1 / (float)price) * rating;
  11. // 返回评分结果
  12. return score;

执行结果如下所示:

28772d759a032a2fec8ca59105cb927c.png

上述脚本通过使用 score 上下文中的 script_score 函数,可以根据自定义逻辑动态计算文档的分数,从而影响搜索结果的排序。

这在需要根据复杂规则排序搜索结果时非常有用。

通过在 Painless Lab 中调试和验证上述脚本,可以确保评分逻辑的正确性和有效性。

进而,可以组合写出如下的评分脚本检索语句。

  1. POST /products/_search
  2. {
  3.   "query": {
  4.     "function_score": {
  5.       "query": {
  6.         "match_all": {}
  7.       },
  8.       "script_score": {
  9.         "script": {
  10.           "source""""
  11.             long price = doc['price'].value;
  12.             double rating = doc['rating'].value;
  13.             
  14.             // 自定义评分逻辑
  15.             double score = (1 / (float)price) * rating;
  16.             return score;
  17.           """
  18.         }
  19.       },
  20.       "boost_mode""replace"  // 使用脚本计算的分数替换原始分数
  21.     }
  22.   }
  23. }

2d0a96da104297695b6f32d4a2f23045.png

实现核心:根据自定义逻辑计算分数:score = (1 / price) * rating。价格越低,评分越高,分数越高。

boost_mode: 设置为 replace,使用脚本计算的分数替换原始分数。

6、小结

Kibana Painless Lab 是 Elasticsearch 7.13 引入的实验性功能,为开发者提供交互式代码编辑器,用于实时测试和调试 Painless 脚本。

通过 painless_test、filter 和 score 上下文三种测试方式,开发者可以创建和调试 Kibana 运行时字段、处理重新索引的数据、定义复杂的 Watcher 条件,并根据复杂规则动态计算文档分数,提高脚本开发和优化效率。

希望大家真正将两篇文章提到的脚本测试方式应用到企业实战环节。

Elasticsearch 企业级实战 01:Painless 脚本如何调试?

探究 | Elasticsearch Painless 脚本 ctx、doc、_source 的区别是什么?

Elasticsearch 脚本安全使用指南

干货 | Elasticsearch7.X Scripting脚本使用详解

新时代写作与互动:《一本书讲透 Elasticsearch》读者群的创新之路

229d9a5be82e1f647b0427258d0bb9f5.png

更短时间更快习得更多干货!

和全球2000+ Elastic 爱好者一起精进!

http://elastic6.cn——ElasticStack进阶助手

5a1aecec32ade0f173cfa8596f298458.gif

抢先一步学习进阶干货!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/861648
推荐阅读
相关标签
  

闽ICP备14008679号