重生之我们在ES顶端相遇第 18 章 - Script 使用(进阶)

news/2024/10/3 14:23:43 标签: elasticsearch

文章目录

      • 0. 前言
      • 1. 基本使用
      • 2. 读请求中访问文档字段
        • 2.1 遍历 List
        • 2.2 判断对象存不存在
        • 2.3 判断值是否为空
        • 2.4 总结
      • 3. 写请求中访问文档字段
        • 3.1 数字相加
        • 3.2 字符串相加
        • 3.3 将字符串转为数组

0. 前言

在前面部分,我们介绍了 ES 的基本使用和要掌握的基础性读写原理。
从本章开始,会开始介绍 ES 进阶使用。
本章要介绍的内容是 Script 的基本使用。
在日常开发中,读请求很少会用,写请求会使用比较多。
在读请求、写请求中,Script 访问文档值的方式有所不同,下面我将对 Script 在读写请求中使用进行介绍。

1. 基本使用

我们来看一个修改算分的例子。

写入文档

PUT test_18/_doc/1
{
  "counter": 1,
  "tags": ["red"],
  "scores": [1,2,3,4,5]
}

查询时,修改算分

GET test_18/_search
{
  "query": {
    "script_score": {
      "query": {
        "term": {
            "tags": "red"
        }
      },
      "script": {
        "lang": "painless",
        "source": "Math.log(_score * 2) + params['my_modifier'] * doc['counter'].value",
        "params": {
          "my_modifier": 2
        }
      }
    }
  }
}

script_score 是 ES 用于修改算分的查询,当然这不是我们的重点。

script 中包含 3 个属性

  • lang: 默认为 painless,非必填
  • source: 脚本,必填
  • params: 传递给脚本的参数,没有定义参数时,不用填

可以看到,在 Script 中我们可以使用 JAVA Api, 可以访问自定义的参数, 可以访问 ES 文档字段值。

2. 读请求中访问文档字段

painless script language 其实跟 JAVA 语法大相径庭。你可以简单认为就是在写 JAVA 代码。

在读请求中,ES 将文档映射为名为 doc 的 map。可以通过 doc['字段名'] 访问对应字段的对象。

2.1 遍历 List
GET test_18/_search
{
  "query": {
      "script_score": {
        "query": {
          "match_all": {}
        },
        "script": {
          "lang": "painless",
          "source": """
            int total = 0;
            for (int i = 0; i < doc['scores'].length; ++i) {
              total += doc['scores'][i];
            }
            return total;
          """
        }
      }
    }
}

代码解释

  • doc['scores'] 获取到文档对象,即 scores 字段
  • .lengthJAVA 数组的方法
  • doc['socere'][i] 访问数组中具体的值

script 中不允许访问 text 字段

GET test_18/_search
{
  "query": {
    "function_score": {
      "script_score": {
        "script": {
          "lang": "painless",
          "source": """
            int total = 0;
            for (int i = 0; i < doc['tags.keyword'].length; ++i) {
              total += doc['counter'].value;
            }
            return total;
          """
        }
      }
    }
  }
}

代码解释

  • doc['tags.keyword'],拿到 tags.keyword 对象。需要特别注意,这里不能使用 doc['tags']因为 ES 在 script 中不允许访问 text 字段
  • doc['counter'],获取 counter 对象。.value 获取 counter 对象的值
2.2 判断对象存不存在

doc.containsKey['field']

GET test_18/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "lang": "painless",
        "source": """
          int total = 0;
          if (doc.containsKey('goals')) {
            return doc['goals'].value;
          } else {
            return (int)_score;
          }
        """
      }
    }
  }
}

代码解释

  • doc.containsKey('goals'): 判断是否包含 goals key。之前我们说过的。文档会被映射为一个 map。因此 doc 具备 map 的函数。
  • return (int)_score: _scorescript_score 中是一个特殊字段。(int) 是类型强转,和 JAVA 语法一致
2.3 判断值是否为空

doc['field'].size()

GET test_18/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "lang": "painless",
        "source": """
          int total = 0;
          if (doc['counter'].size() == 0) {
            return 3;
          } else {
            return 2;
          }
        """
      }
    }
  }
}

代码解释

  • doc['counter'].size() 获取 counter 对象长度
2.4 总结
  1. 读请求中,可以使用 doc['字段名'] 访问对应字段的对象
  2. script 读请求中,无法访问 text 字段
  3. painless 语法与 JAVA 语法类似
  4. 关于 painless 更多可阅读 ES painless 官网
  5. painless 中可以使用哪些 API,可以参考 painless 支持的 API 文档

3. 写请求中访问文档字段

在写请求中使用脚本,我们大部分情况下是结合 Ingest Pipeline 一起使用。
Ingest pipeline 中,通过 ctx.xxx 就可以访问到文档字段。

注:Ingest pipeline:可以在文档写入前对文档进行预处理。

下面,我们来看几个例子

3.1 数字相加

将 math_score + verbal_score 赋值给 total_score

创建索引

PUT test_18_write_01
{
  "mappings": {
    "properties": {
      "math_score": {
        "type": "integer"
      },
      "verbal_score": {
        "type": "integer"
      },
      "total_score": {
        "type": "integer"
      }
    }
  }
}

创建 ingest pipeline

PUT _ingest/pipeline/test_18_write_01_pipeline
{
  "description": "Calculates the total test score",
  "processors": [
    {
      "script": {
        "source": "ctx.total_score = (ctx.math_score + ctx.verbal_score)"
      }
    }
  ]
}

写入时,指定 pipeline

PUT test_18_write_01/_doc/1?pipeline=test_18_write_01_pipeline
{
  "math_score": 99,
  "verbal_score": 89
}

查看结果

GET test_18_write_01/_search

在这里插入图片描述

已经为我们自动写入了 total_score

3.2 字符串相加

将 lastName、firstName 相加,赋值给 fullName

创建 ingest pipeline

PUT _ingest/pipeline/test_18_write_02_pipeline
{
  "description": "String concatenation test",
  "processors": [
    {
      "script": {
        "source": """
          if (ctx.containsKey('lastName') && ctx.containsKey('firstName')) {
            ctx.fullName = ctx.lastName + ' ' + ctx.firstName;
          }
        """
      }
    }
  ]
}

写入文档,并指定 pipeline

PUT test_18_write_02/_doc/1?pipeline=test_18_write_02_pipeline
{
  "firstName": "hello",
  "lastName": "elasticsearch"
}
3.3 将字符串转为数组

将 name 转换为数组,并赋值给 names

创建 pipeline

PUT _ingest/pipeline/test_18_write_03_pipeline
{
   "description": "string to array",
   "processors": [
      {
        "script": {
          "source": """
            ctx.names = ctx.name.splitOnToken(',')
          """
        }
      }
    ]
}

写入数据,并指定 pipeline

PUT test_18_write_03/_doc/1?pipeline=test_18_write_03_pipeline
{
  "name": "hello,elasticsearch"
}

http://www.niftyadmin.cn/n/5688516.html

相关文章

微信小程序数据操作指南:从绑定到更新

微信小程序数据操作指南&#xff1a;从绑定到更新 在微信小程序开发中&#xff0c;数据操作是核心环节之一。微信小程序提供了一系列简洁而强大的数据操作方法&#xff0c;帮助开发者轻松实现数据的绑定、更新和渲染。本文将详细介绍微信小程序中常用的数据操作方法&#xff0…

MySQL 启动失败 (code=exited, status=1/FAILURE) 异常解决方案

目录 前言1. 问题描述2. 查看错误日志文件2.1 确认日志文件路径2.2 查看日志文件内容 3. 定位问题3.1 问题分析 4. 解决问题4.1 注释掉错误配置4.2 重启 MySQL 服务 5. 总结结语 前言 在日常运维和开发过程中&#xff0c;MySQL数据库的稳定运行至关重要。然而&#xff0c;MySQ…

视频加字幕免费软件哪个好用?详细介绍6款字幕编辑软件的优缺点!码住!

视频加字幕免费软件哪个好用&#xff1f;在视频制作和编辑的过程中&#xff0c;字幕的添加是不可或缺的一环。它不仅能帮助观众更好地理解视频内容&#xff0c;还能提升视频的专业度和观赏性。然而&#xff0c;面对市场上琳琅满目的视频加字幕软件&#xff0c;如何选择一款既免…

推荐 uniapp 相对好用的海报生成插件

插件地址&#xff1a;自定义canvas样式海报 - DCloud 插件市场 兼容性也是不错的&#xff1a;

C++11 异步操作 std::future类

阅读导航 引言一、异步的概念二、应用场景1. 异步任务处理2. 并发控制3. 结果获取 三、使用示例1. 使用std::async关联异步任务&#x1f4bb;示例代码说明 2. 使用std::packaged_task和std::future配合&#xff08;1&#xff09;定义std::packaged_task&#xff08;2&#xff0…

【MySQL】子查询、合并查询、表的连接

目录 一、子查询 1、单行子查询 显示SMITH同一部门的员工信息 2、多行子查询 in关键字 查询和10号部门的工作岗位相同的雇员的名字、岗位、工资、部门号&#xff0c;但是筛选出的雇员的部门不能有10号部门 all关键字 查询工资比30号部门中所有雇员工资高的雇员的姓名、…

MFC工控项目实例二十一型号选择界面删除参数按钮禁用切换

承接专栏《MFC工控项目实例二十手动测试界面模拟量输入实时显示》 对于禁止使用的删除、参数按钮&#xff0c;在选中列表控件选项时切换为能够使用。 1、在TypDlg.h文件中添加代码 #include "ShadeButtonST.h" #include "BtnST.h" class CTypDlg : publi…

【洛谷】AT_abc373_c [ABC373D] Hidden Weights 的题解

【洛谷】AT_abc373_c [ABC373D] Hidden Weights 的题解 洛谷传送门 AT传送门 题解 本地WA&#xff0c;提交AC&#xff0c;奇迹 AT&#xff0c;奇迹评测机 题目大意&#xff1a; 给定 n n n 个点&#xff0c; m m m 条有向边&#xff0c;每条有向边从 u i u_i ui​ 指向…