elasticsearch - 在 Painless/ELK 中拆分字符串
问题描述
我有一个字符串字段“myfield.keyword”,其中条目具有以下格式:
AAA_BBBB_CC
DDD_EEE_F
我正在尝试创建一个在第一个 _ 之前输出子字符串的脚本字段,一个在第一个和第二个 _ 之间输出子字符串的脚本字段,以及一个在第二个 _ 之后输出子字符串的脚本字段。
我试图使用 .split('_') 来执行此操作,但发现此方法在 Painless 中不可用:
def newfield = "";
def path = doc[''myfield.keyword].value;
if (...)
{newfield = path.split('_')[1];} else {newfield="null";}
return newfield
然后我尝试了此处建议的解决方法,但发现我必须在 Elastic 中启用正则表达式(在我的情况下这是不可能的):
def newfield = "";
def path = doc[''myfield.keyword].value;
if (...)
{newfield = /_/.split(path)[1];} else {newfield="null";}
return newfield
有没有办法做到这一点,前提是启用正则表达式?
编辑:
感谢您提供如此优雅的解决方案 Val。这回答了我问的问题。然而,我的问题没有很好地形成。特别是,需要拆分的字符串有四次出现'_'。就像是:
AAA_BB_CCC_DD_E
FFF_GGG_HH_JJJJ_KK
所以,如果我理解正确,indexOf()
不能lastIndexOf()
给我BB、CCC或DD。我认为我可以调整您的解决方案,并使用 and 找到第二次和第三次出现 _ 的string.indexOf("_", 1)
索引string.indexOf("_", 2)
。但是,我总是得到与 相同的结果string.indexOf("_")
,没有任何额外的参数(即结果总是 _ 的第一次出现的索引)。
解决方案
启用正则表达式并不是非常复杂,但它需要重新启动集群,并且根据环境的不同,这对您来说可能并不容易。
实现这一目标的另一种方法是使用“旧方式”。首先,您为每个脚本字段创建一个可重用的脚本。该脚本所做的只是查找_
符号的第一次、第二次、第三次和最后一次出现并返回拆分元素。它将要拆分的字段名称和要返回的子字符串的索引作为输入:
POST _scripts/my-split
{
"script": {
"lang": "painless",
"source": """
def str = doc[params.field].value;
def first = str.indexOf("_");
def second = first + 1 + str.substring(first + 1).indexOf("_");
def third = second + 1 + str.substring(second + 1).indexOf("_");
def last = str.lastIndexOf("_");
def parts = [
str.substring(0, first),
str.substring(first + 1, second),
str.substring(second + 1, third),
str.substring(third + 1, last),
str.substring(last + 1)
];
return parts[params.index];
"""
}
}
然后,您可以像这样简单地为每个部分定义一个脚本字段:
POST test/_search
{
"script_fields": {
"first": {
"script": {
"id": "my-split",
"params": {
"field": "myfield.keyword",
"index": 0
}
}
},
"second": {
"script": {
"id": "my-split",
"params": {
"field": "myfield.keyword",
"index": 1
}
}
},
"third": {
"script": {
"id": "my-split",
"params": {
"field": "myfield.keyword",
"index": 2
}
}
}
}
}
您得到的响应将如下所示:
{
"_index" : "test",
"_type" : "_doc",
"_id" : "ykS-l3UBeO1HTBdDvTZd",
"_score" : 1.0,
"fields" : {
"first" : [
"AAA"
],
"second" : [
"BBBB"
],
"third" : [
"CC"
]
}
}
推荐阅读
- excel - 取消选择范围后将复制的范围保留在剪贴板中
- breeze - 带有角度/微风客户端代码的示例 ASP.Net Core Breeze 服务器?
- c - C - 在从函数返回双指针之前初始化二维数组中的结构
- debugging - ASP.NET Core - 无法附加到 w3wp
- autocad - 通过 AutoCAD 中的表格更改自定义块内容
- javascript - 如何在 Apollo GraphQL 解析器的一个函数中解析 2 种不同的方法?
- php - .htaccess 重写规则是否导致我的查询字符串为空?
- angular - 不获取反应形式的输入值(Angular5)
- c++ - 为什么添加更多变量和/或指令后程序大小保持不变?
- reactjs - 从 react PWA 中读取 BLE 信标