2

我正在尝试使用 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 来进行计算并添加一个单独的字段

- 更新。

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

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

返回

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

-- 更新 2

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

4

3 回答 3

2

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

我在同一个文档中发现了一个提示:

文档值是列字段值存储

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

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

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

对 doc 值的一些更深入的研究揭示了它是一种压缩技术,该技术实际上对值进行去重以实现高效和内存友好的操作。

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

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

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

此外,如果您不想要这种行为,那么您可以禁用 doc-values

于 2019-06-21T21:20:14.487 回答
1

好的,解决了。

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

因此,正如我发现的那样,数组被预过滤为只返回不同的值(显然是 int 的情况除外?)

解决方案是使用params._source而不是doc[]

于 2019-06-20T16:02:51.820 回答
1

doc为什么不起作用的答案

引用如下:

文档值是一个列字段值存储,默认情况下在所有字段上启用,除了分析的文本字段。

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

此外,重要的是添加如下所述的空检查

缺少字段

如果映射中缺少字段,则 doc['field'] 将引发错误。在无痛的情况下,可以首先使用 doc.containsKey('field')* 进行检查,以防止访问 doc map。不幸的是,没有办法在表达式脚本的映射中检查字段是否存在。

另外,这就是为什么_source有效

引用如下:

可以使用 _source.field_name 语法访问文档 _source,它实际上只是一个特殊的存储字段。_source 作为 map-of-maps 加载,因此对象字段中的属性可以作为例如 _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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
于 2019-06-20T20:03:28.480 回答