【问题标题】:Kibana scripted field which loops through an array遍历数组的 Kibana 脚本字段
【发布时间】:2019-06-20 15:00:11
【问题描述】:

我正在尝试使用 metricbeat http 模块来监控 F5 池。

我向 f5 api 发出请求并带回保存到 kibana 的 json。但是 json 包含一个池成员数组,我想计算其中的数量。

建议似乎可以通过脚本字段来完成。但是,我无法获取脚本来检索数组。例如

doc['http.f5pools.items.monitor'].value.length()

在预览结果中返回添加了相同的“附加字段”以进行比较:

[
 {
  "_id": "rT7wdGsBXQSGm_pQoH6Y",
  "http": {
   "f5pools": {
    "items": [
     {
      "monitor": "default"
     },
     {
      "monitor": "default"
     }
    ]
   }
  },
  "pool.MemberCount": [
   7
  ]
 },

如果我尝试

doc['http.f5pools.items']

或者类似的,我只是得到一个错误:

"reason": "No field found for [http.f5pools.items] in mapping with types []"

谷歌搜索表明 doc 构造不包含数组?

  1. 是否可以创建一个可以访问该组值的脚本字段?即是我的代码或我索引数据的方式错误。
  2. 如果没有,metricbeats 中是否有替代方法?我不想制作一个全新的 api 来进行计算并添加一个单独的字段

--更新。

奇怪的是,数组中的数值似乎确实返回了预期的结果。即。

doc['http.f5pools.items.ratio']

返回

 {
  "_id": "BT6WdWsBXQSGm_pQBbCa",
  "pool.MemberCount": [
   1,
   1
  ]
 },

-- 更新 2

好的,所以如果字段中的字符串具有不同的值,那么您将获得所有值。如果它们是相同的,你就得到一个。什么鬼?

【问题讨论】:

    标签: elasticsearch kibana metricbeat


    【解决方案1】:

    我正在添加另一个答案,而不是删除我以前的答案,这不是实际问题,但将来仍可能对其他人有所帮助。

    我在same documentation找到了提示:

    Doc 值是一个列字段值存储

    在谷歌上进一步搜索后,我发现了这个Doc Value Intro,它说文档值本质上是“未倒排索引”,对于排序等操作很有用;我的假设是,在排序时,您基本上不希望重复相同的值,因此他们使用的数据结构会删除那些重复项。那仍然没有回答为什么它对字符串的工作方式与数字不同。数字被保留,但字符串被过滤成唯一的。

    这种“未倒置”结构在其他领域通常被称为“列存储” 系统。本质上,它存储单个字段的所有值 在一列数据中,这使得它非常有效 排序等操作。

    在 Elasticsearch 中,这个列存储被称为 doc values,并且是 默认启用。文档值是在索引时创建的:当一个字段 被索引后,Elasticsearch 将标记添加到倒排索引中 搜索。但它也会提取术语并将它们添加到柱状 文档值。

    更多 deep-dive into doc values revealed it a compression technique 实际上对值进行去重以实现高效且内存友好的操作。

    这是上面链接中给出的回答问题的注释:

    您可能会想“这对数字来说很好,但那又如何呢? 字符串?”字符串的编码方式类似,在序数的帮助下 桌子。 字符串被重复删除并排序到一个表中,分配 一个 ID,然后将这些 ID 用作数字文档值。意思是 字符串享有与数字相同的许多压缩优势。

    序数表本身有一些压缩技巧,比如使用 固定、可变或前缀编码的字符串。

    另外,如果你不想要这种行为,那么你可以disable doc-values

    【讨论】:

    • 我想你找到了。关于 kibana/elastic 似乎有一些不直观的事情
    • 是的,这更多是在数据结构部分,不太容易理解。但肯定很高兴知道。感谢分享
    【解决方案2】:

    好的,解决了。

    https://discuss.elastic.co/t/problem-looping-through-array-in-each-doc-with-painless/90648

    所以我发现数组被预过滤为只返回不同的值(显然是 int 的情况除外?)

    解决办法是用params._source代替doc[]

    【讨论】:

    • 如果有人能解释为什么我会接受你的回答
    【解决方案3】:

    The answer for why doc doesnt work

    引用如下:

    Doc 值是一个列字段值存储,默认情况下在所有 分析的文本字段除外。

    Doc-values 只能返回“简单”字段值,如数字、日期、 地理点、术语等,或这些值的数组,如果该字段是 多值。它不能返回 JSON 对象

    另外,添加 null 检查 也很重要,如下所述:

    缺少字段

    如果字段是 doc['field'] 将抛出错误 从映射中丢失。在无痛的情况下,可以先进行检查 doc.containsKey('field')* 来保护访问文档映射。 不幸的是,没有办法检查该字段是否存在 在表达式脚本中的映射中。

    Also, here is why _source works

    引用如下:

    文档_source,其实只是一个特殊的存储字段,可以 使用 _source.field_name 语法访问。 _source 已加载 作为地图的地图,因此可以访问对象字段中的属性 例如,_source.name.first。

    .

    用一个例子来回应你的评论:

    这里的关键字是:它不能返回 JSON 对象。字段 doc['http.f5pools.items'] 是一个 JSON 对象

    尝试在下面运行并查看它创建的映射:

    PUT t5/doc/2
    {
       "items": [
         {
          "monitor": "default"
         },
         {
          "monitor": "default"
         }
        ]
    }
    
    
    GET t5/_mapping
    
    {
      "t5" : {
        "mappings" : {
          "doc" : {
            "properties" : {
              "items" : {
                "properties" : {
                  "monitor" : {  <-- monitor is a property of items property(Object)
                    "type" : "text",
                    "fields" : {
                      "keyword" : {
                        "type" : "keyword",
                        "ignore_above" : 256
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    

    【讨论】:

    • 是的,这取决于值和映射。不管它分析与否。答案都在文档中。
    • 您能否指出文档中的说明,当值是字符串时,数组被预过滤为唯一值?
    • 它没有说那些确切的词,但它说 它不能返回 JSON 对象doc['http.f5pools.items'] 字段是一个 JSON 对象。
    • @Ewan 还添加了一个示例。希望这会增加一些清晰度
    • 我认为你没有抓住重点。我知道它不能返回对象。但它可以将对象的字段作为数组返回。除了,当字段类型是字符串时,它只返回 distinct 值而不是所有值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 2020-05-29
    • 1970-01-01
    • 2016-03-01
    • 2021-10-11
    相关资源
    最近更新 更多