Vega编辑

VegaVega-Lite 都是用于创建自定义可视化的语法。它们推荐给习惯手动编写 Elasticsearch 查询的高级用户。 Vega-Lite 是对两种语法都不熟悉的用户的一个良好起点,但它们不兼容。

VegaVega-Lite 面板可以显示一个或多个数据源,包括 Elasticsearch、Elastic Map Service、URL 或静态数据,并支持 Kibana 扩展,允许您将面板嵌入到仪表盘中并添加交互式工具。

当您想要创建具有以下功能的可视化时,请使用 VegaVega-Lite

  • 使用 nestedparent/child 映射的聚合
  • 没有数据视图的聚合
  • 使用自定义时间过滤器的查询
  • 复杂计算
  • 从 _source 中提取的数据而不是聚合
  • 散点图、桑基图和自定义地图
  • 不支持的视觉主题

这些语法有一些限制:它们不支持表格,并且不能有条件地运行查询。

Vega UI

VegaVega-Lite 都使用 JSON,但 Kibana 通过集成 HJSON 使其更易于键入。HJSON 支持以下内容

  • 可选引号
  • 双引号或单引号
  • 可选逗号
  • 使用 // 或 /* 语法的注释
  • 多行字符串

教程:创建自定义面板编辑

了解如何将 Vega-Lite 与 Kibana 过滤器和 Elasticsearch 数据连接,然后了解如何使用 Vega 创建更多 Kibana 交互。

在编辑规范时,请分步操作,并经常保存您的工作。小的更改可能会导致意外结果。要保存,请单击工具栏中的 保存

在开始之前,请添加您将在规范中使用的电子商务示例数据,然后创建仪表盘。

  1. 在主页上,单击 尝试示例数据
  2. 单击 其他示例数据集
  3. 示例电子商务订单 卡上,单击 添加数据
  4. 打开主菜单,然后单击 仪表盘
  5. 仪表盘 页面上,单击 创建仪表盘
打开并设置 Vega-Lite编辑

打开 Vega-Lite 并更改时间范围。

  1. 在仪表盘上,单击 选择类型,然后选择 自定义可视化

    一个预先填充的折线图显示了文档总数。

  2. 确保 时间过滤器过去 7 天

教程:从 Elasticsearch 搜索查询创建堆叠区域图编辑

了解如何从 Vega-Lite 查询 Elasticsearch,并将结果显示在堆叠区域图中。

  1. Vega-Lite 规范中,将 index: _all 替换为以下内容,然后单击 更新
index: kibana_sample_data_ecommerce

出现一条结果为零的平线。

要添加来自 kibana_sample_data_ecommerce 数据视图的数据字段,请替换以下内容,然后单击 更新

  • %timefield%: @timestamp with %timefield%: order_date
  • field: @timestamp with field: order_date
添加聚合编辑

要创建堆叠区域图,请添加聚合。

要检查您的工作,请在单独的浏览器选项卡中打开并使用 控制台

  1. 在新的选项卡中打开 Kibana。
  2. 打开主菜单,然后单击 开发工具
  3. 控制台 编辑器中,输入聚合,然后单击 单击以发送请求
POST kibana_sample_data_ecommerce/_search
{
  "query": {
    "range": {
      "order_date": {
        "gte": "now-7d"
      }
    }
  },
  "aggs": {
    "time_buckets": {
      "date_histogram": {
        "field": "order_date",
        "fixed_interval": "1d",
        "extended_bounds": {
          "min": "now-7d"
        },
        "min_doc_count": 0
      }
    }
  },
  "size": 0
}

添加 terms 聚合,然后单击 单击以发送请求

POST kibana_sample_data_ecommerce/_search
{
  "query": {
    "range": {
      "order_date": {
        "gte": "now-7d"
      }
    }
  },
  "aggs": {
    "categories": {
      "terms": { "field": "category.keyword" },
      "aggs": {
        "time_buckets": {
          "date_histogram": {
            "field": "order_date",
            "fixed_interval": "1d",
            "extended_bounds": {
              "min": "now-7d"
            },
            "min_doc_count": 0
          }
        }
      }
    }
  },
  "size": 0
}

响应格式与第一个聚合查询不同

{
  "aggregations" : {
    "categories" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [{
        "key" : "Men's Clothing",
        "doc_count" : 1661,
        "time_buckets" : {
          "buckets" : [{
            "key_as_string" : "2020-06-30T00:00:00.000Z",
            "key" : 1593475200000,
            "doc_count" : 19
          }, {
            "key_as_string" : "2020-07-01T00:00:00.000Z",
            "key" : 1593561600000,
            "doc_count" : 71
          }]
        }
      }]
    }
  }
}

Vega-Lite 规范中,输入聚合,然后单击 更新

  data: {
    url: {
      %context%: true
      %timefield%: order_date
      index: kibana_sample_data_ecommerce
      body: {
        aggs: {
          categories: {
            terms: { field: "category.keyword" }
            aggs: {
              time_buckets: {
                date_histogram: {
                  field: order_date
                  interval: {%autointerval%: true}
                  extended_bounds: {
                    min: {%timefilter%: "min"}
                    max: {%timefilter%: "max"}
                  }
                  min_doc_count: 0
                }
              }
            }
          }
        }
        size: 0
      }
    }
    format: {property: "aggregations.categories.buckets" }
  }

有关查询的信息,请参阅 在 Vega 中编写 Elasticsearch 查询的参考

调试警告编辑

要生成数据,Vega-Lite 使用 source_0data_0source_0 包含 Elasticsearch 查询的结果,data_0 包含显示在图表上的视觉编码结果。要调试警告,请比较 source_0data_0

  1. 在工具栏中,单击 检查
  2. 视图 下拉菜单中,选择 Vega 调试
  3. 从下拉菜单中,选择 source_0

    Table for data_0 with columns key
  4. 要与视觉编码数据进行比较,请从下拉菜单中选择 data_0

    Table for data_0 where the key is NaN instead of a string

    key 无法转换,因为属性是类别(Men's ClothingWomen's Clothing 等),而不是时间戳。

添加并调试编码块编辑

Vega-Lite 规范中,添加 encoding

  encoding: {
    x: {
      field: time_buckets.buckets.key
      type: temporal
      axis: { title: null }
    }
    y: {
      field: time_buckets.buckets.doc_count
      type: quantitative
      axis: { title: "Document count" }
    }
  }
  1. 单击 检查,然后从 视图 下拉菜单中选择 Vega 调试
  2. 从下拉菜单中,选择 data_0

    Table for data_0 showing that the column time_buckets.buckets.key is undefined

Vega-Lite 无法提取 time_buckets.buckets 内部数组。

提取 time_buckets.buckets 内部数组编辑

在 Kibana 7.9 及更高版本中,使用 Vega-Lite flatten 变换 来提取 time_buckets.buckets 内部数组。

如果您使用的是 Kibana 7.8 及更早版本,则 flatten 变换仅在 Vega 中可用。

Vega-Lite 规范中,添加一个 transform 块,然后单击 更新

  transform: [{
    flatten: ["time_buckets.buckets"]
  }]
  1. 单击 检查,然后从 视图 下拉菜单中选择 Vega 调试
  2. 从下拉菜单中,选择 data_0

    Table showing data_0 with multiple pages of results

    Vega-Lite 显示 undefined 值,因为存在重复的名称。

  3. 要解决重复的名称,请添加 transformencoding 块,然后单击 更新
  transform: [{
    flatten: ["time_buckets.buckets"],
    as: ["buckets"]
  }]

  mark: area

  encoding: {
    x: {
      field: buckets.key
      type: temporal
      axis: { title: null }
    }
    y: {
      field: buckets.doc_count
      type: quantitative
      axis: { title: "Document count" }
    }
    color: {
      field: key
      type: nominal
    }
  }
添加悬停状态和工具提示编辑

使用 Vega-Lite 规范,您可以使用 selection 块将悬停状态和工具提示添加到堆叠区域图中。

Vega-Lite 规范中,添加 encoding 块,然后单击 更新

  encoding: {
    tooltip: [{
      field: buckets.key
      type: temporal
      title: "Date"
    }, {
      field: key
      type: nominal
      title: "Category"
    }, {
      field: buckets.doc_count
      type: quantitative
      title: "Count"
    }]
  }

当您将鼠标悬停在堆叠区域图上的区域序列上时,会出现一个多行工具提示,但无法指示最近的点。要指示最近的点,请添加第二层。

添加复合标记,然后单击 更新

  layer: [{
    mark: area
  }, {
    mark: point
  }]

这些点无法堆叠并与堆叠区域图对齐。

更改 y encoding

    y: {
      field: buckets.doc_count
      type: quantitative
      axis: { title: "Document count" }
      stack: true
    }

mark: point 内添加一个 selection

  layer: [{
    mark: area
  }, {
    mark: point

    selection: {
      pointhover: {
        type: single
        on: mouseover
        clear: mouseout
        empty: none
        fields: ["buckets.key", "key"]
        nearest: true
      }
    }

    encoding: {
      size: {
        condition: {
          selection: pointhover
          value: 100
        }
        value: 5
      }
      fill: {
        condition: {
          selection: pointhover
          value: white
        }
      }
    }
  }]

将鼠标移动到堆叠区域图周围。这些点能够指示最近的点。

Vega-Lite tutorial selection enabled

选择由信号控制。要查看信号,请单击工具栏中的 检查

展开最终的 Vega-Lite 规范
{
  $schema: https://vega.github.io/schema/vega-lite/v4.json
  title: Event counts from ecommerce
  data: {
    url: {
      %context%: true
      %timefield%: order_date
      index: kibana_sample_data_ecommerce
      body: {
        aggs: {
          categories: {
            terms: { field: "category.keyword" }
            aggs: {
              time_buckets: {
                date_histogram: {
                  field: order_date
                  interval: {%autointerval%: true}
                  extended_bounds: {
                    min: {%timefilter%: "min"}
                    max: {%timefilter%: "max"}
                  }
                  min_doc_count: 0
                }
              }
            }
          }
        }
        size: 0
      }
    }
    format: {property: "aggregations.categories.buckets" }
  }

  transform: [{
    flatten: ["time_buckets.buckets"]
    as: ["buckets"]
  }]

  encoding: {
    x: {
      field: buckets.key
      type: temporal
      axis: { title: null }
    }
    y: {
      field: buckets.doc_count
      type: quantitative
      axis: { title: "Document count" }
      stack: true
    }
    color: {
      field: key
      type: nominal
      title: "Category"
    }
    tooltip: [{
      field: buckets.key
      type: temporal
      title: "Date"
    }, {
      field: key
      type: nominal
      title: "Category"
    }, {
      field: buckets.doc_count
      type: quantitative
      title: "Count"
    }]
  }

  layer: [{
    mark: area
  }, {
    mark: point

    selection: {
      pointhover: {
        type: single
        on: mouseover
        clear: mouseout
        empty: none
        fields: ["buckets.key", "key"]
        nearest: true
      }
    }

    encoding: {
      size: {
        condition: {
          selection: pointhover
          value: 100
        }
        value: 5
      }
      fill: {
        condition: {
          selection: pointhover
          value: white
        }
      }
    }
  }]
}

教程:从 Vega 更新 Kibana 过滤器编辑

要使用 Elasticsearch 搜索查询构建区域图,请编辑 Vega 规范,然后添加单击和拖动处理程序以更新 Kibana 过滤器。

Vega 规范中,输入以下内容,然后单击 更新

{
  $schema: "https://vega.github.io/schema/vega/v5.json"
  data: [{
    name: source_0
  }]

  scales: [{
    name: x
    type: time
    range: width
  }, {
    name: y
    type: linear
    range: height
  }]

  axes: [{
    orient: bottom
    scale: x
  }, {
    orient: left
    scale: y
  }]

  marks: [
    {
      type: area
      from: {
        data: source_0
      }
      encode: {
        update: {
        }
      }
    }
  ]
}

使用 data 块添加 Elasticsearch 搜索查询,然后单击 更新

  data: [
    {
      name: source_0
      url: {
        %context%: true
        %timefield%: order_date
        index: kibana_sample_data_ecommerce
        body: {
          aggs: {
            time_buckets: {
              date_histogram: {
                field: order_date
                fixed_interval: "3h"
                extended_bounds: {
                  min: {%timefilter%: "min"}
                  max: {%timefilter%: "max"}
                }
                min_doc_count: 0
              }
            }
          }
          size: 0
        }
      }
      format: { property: "aggregations.time_buckets.buckets" }
    }
  ]
更改 X 轴和 Y 轴编辑

显示 X 轴和 Y 轴的标签。

Vega 规范中,添加 scales 块,然后单击 更新

  scales: [{
    name: x
    type: time
    range: width
    domain: {
      data: source_0
      field: key
    }
  }, {
    name: y
    type: linear
    range: height
    domain: {
      data: source_0
      field: doc_count
    }
  }]

keydoc_count 字段添加为 X 轴和 Y 轴值,然后单击 更新

  marks: [
    {
      type: area
      from: {
        data: source_0
      }
      encode: {
        update: {
          x: {
            scale: x
            field: key
          }
          y: {
            scale: y
            value: 0
          }
          y2: {
            scale: y
            field: doc_count
          }
        }
      }
    }
  ]
vega tutorial 3
marks 部分添加一个块edit

在面积图上显示可点击的点,以便过滤特定日期。

Vega 规范中,添加到 marks 块,然后点击 更新

  {
    name: point
    type: symbol
    style: ["point"]
    from: {
      data: source_0
    }
    encode: {
      update: {
        x: {
          scale: x
          field: key
        }
        y: {
          scale: y
          field: doc_count
        }
        size: {
          value: 100
        }
        fill: {
          value: black
        }
      }
    }
  }
创建一个信号edit

为了使点可点击,创建一个 Vega 信号。您可以在用于更新的表达式中访问点击的 datum

Vega 规范中,添加一个 signals 块,以指定光标点击添加一个具有三小时间隔的时间过滤器,然后点击 更新

  signals: [
    {
      name: point_click
      on: [{
        events: {
          source: scope
          type: click
          markname: point
        }
        update: '''kibanaSetTimeFilter(datum.key, datum.key + 3 * 60 * 60 * 1000)'''
      }]
    }
  ]

该事件使用 kibanaSetTimeFilter 自定义函数来生成一个过滤器,该过滤器在点击时应用于整个仪表板。

为了使面积图交互式,找到 marks 块,然后更新 point 并将 cursor: { value: "pointer" } 添加到 encoding

  {
    name: point
    type: symbol
    style: ["point"]
    from: {
      data: source_0
    }
    encode: {
      update: {
        ...
        cursor: { value: "pointer" }
      }
    }
  }
添加拖动交互edit

为了允许用户根据时间范围进行过滤,添加一个拖动交互,这需要额外的信号和一个矩形覆盖。

vega tutorial 4

Vega 规范中,添加一个 signal 来跟踪光标的 X 位置

    {
      name: currentX
      value: -1
      on: [{
        events: {
          type: mousemove
          source: view
        },
        update: "clamp(x(), 0, width)"
      }, {
        events: {
          type: mouseout
          source: view
        }
        update: "-1"
      }]
    }

为了指示当前光标位置,添加一个 mark

    {
      type: rule
      interactive: false
      encode: {
        update: {
          y: {value: 0}
          y2: {signal: "height"}
          stroke: {value: "gray"}
          strokeDash: {
            value: [2, 1]
          }
          x: {signal: "max(currentX,0)"}
          defined: {signal: "currentX > 0"}
        }
      }
    }

为了跟踪选定的时间范围,添加一个信号,该信号在用户释放光标或按下回车键之前一直更新

    {
      name: selected
      value: [0, 0]
      on: [{
        events: {
          type: mousedown
          source: view
        }
        update: "[clamp(x(), 0, width), clamp(x(), 0, width)]"
      }, {
        events: {
          type: mousemove
          source: window
          consume: true
          between: [{
            type: mousedown
            source: view
          }, {
            merge: [{
              type: mouseup
              source: window
            }, {
              type: keydown
              source: window
              filter: "event.key === 'Escape'"
            }]
          }]
        }
        update: "[selected[0], clamp(x(), 0, width)]"
      }, {
        events: {
          type: keydown
          source: window
          filter: "event.key === 'Escape'"
        }
        update: "[0, 0]"
      }]
    }

有一个信号跟踪来自用户的時間範圍。

为了在视觉上指示范围,添加一个仅在特定条件下显示的标记

    {
      type: rect
      name: selectedRect
      encode: {
        update: {
          height: {signal: "height"}
          fill: {value: "#333"}
          fillOpacity: {value: 0.2}
          x: {signal: "selected[0]"}
          x2: {signal: "selected[1]"}
          defined: {signal: "selected[0] !== selected[1]"}
        }
      }
    }

添加一个信号,在拖动时释放光标时更新 Kibana 时间过滤器

    {
      name: applyTimeFilter
      value: null
      on: [{
        events: {
          type: mouseup
          source: view
        }
        update: '''selected[0] !== selected[1] ? kibanaSetTimeFilter(
               invert('x',selected[0]),
               invert('x',selected[1])) : null'''
      }]
    }
扩展最终的 Vega 规范
{
  $schema: "https://vega.github.io/schema/vega/v5.json"
  data: [
    {
      name: source_0
      url: {
        %context%: true
        %timefield%: order_date
        index: kibana_sample_data_ecommerce
        body: {
          aggs: {
            time_buckets: {
              date_histogram: {
                field: order_date
                fixed_interval: "3h"
                extended_bounds: {
                  min: {%timefilter%: "min"}
                  max: {%timefilter%: "max"}
                }
                min_doc_count: 0
              }
            }
          }
          size: 0
        }
      }
      format: { property: "aggregations.time_buckets.buckets" }
    }
  ]

  scales: [{
    name: x
    type: time
    range: width
    domain: {
      data: source_0
      field: key
    }
  }, {
    name: y
    type: linear
    range: height
    domain: {
      data: source_0
      field: doc_count
    }
  }]

  axes: [{
    orient: bottom
    scale: x
  }, {
    orient: left
    scale: y
  }]

  marks: [
    {
      type: area
      from: {
        data: source_0
      }
      encode: {
        update: {
          x: {
            scale: x
            field: key
          }
          y: {
            scale: y
            value: 0
          }
          y2: {
            scale: y
            field: doc_count
          }
        }
      }
    },
    {
      name: point
      type: symbol
      style: ["point"]
      from: {
        data: source_0
      }
      encode: {
        update: {
          x: {
            scale: x
            field: key
          }
          y: {
            scale: y
            field: doc_count
          }
          size: {
            value: 100
          }
          fill: {
            value: black
          }
          cursor: { value: "pointer" }
        }
      }
    },
    {
      type: rule
      interactive: false
      encode: {
        update: {
          y: {value: 0}
          y2: {signal: "height"}
          stroke: {value: "gray"}
          strokeDash: {
            value: [2, 1]
          }
          x: {signal: "max(currentX,0)"}
          defined: {signal: "currentX > 0"}
        }
      }
    },
    {
      type: rect
      name: selectedRect
      encode: {
        update: {
          height: {signal: "height"}
          fill: {value: "#333"}
          fillOpacity: {value: 0.2}
          x: {signal: "selected[0]"}
          x2: {signal: "selected[1]"}
          defined: {signal: "selected[0] !== selected[1]"}
        }
      }
    }
  ]

  signals: [
    {
      name: point_click
      on: [{
        events: {
          source: scope
          type: click
          markname: point
        }
        update: '''kibanaSetTimeFilter(datum.key, datum.key + 3 * 60 * 60 * 1000)'''
      }]
    }
    {
      name: currentX
      value: -1
      on: [{
        events: {
          type: mousemove
          source: view
        },
        update: "clamp(x(), 0, width)"
      }, {
        events: {
          type: mouseout
          source: view
        }
        update: "-1"
      }]
    }
    {
      name: selected
      value: [0, 0]
      on: [{
        events: {
          type: mousedown
          source: view
        }
        update: "[clamp(x(), 0, width), clamp(x(), 0, width)]"
      }, {
        events: {
          type: mousemove
          source: window
          consume: true
          between: [{
            type: mousedown
            source: view
          }, {
            merge: [{
              type: mouseup
              source: window
            }, {
              type: keydown
              source: window
              filter: "event.key === 'Escape'"
            }]
          }]
        }
        update: "[selected[0], clamp(x(), 0, width)]"
      }, {
        events: {
          type: keydown
          source: window
          filter: "event.key === 'Escape'"
        }
        update: "[0, 0]"
      }]
    }
    {
      name: applyTimeFilter
      value: null
      on: [{
        events: {
          type: mouseup
          source: view
        }
        update: '''selected[0] !== selected[1] ? kibanaSetTimeFilter(
               invert('x',selected[0]),
               invert('x',selected[1])) : null'''
      }]
    }
  ]
}

Vega 参考edit

了解有关 Kibana 扩展、其他 Vega 资源和示例的更多信息。

Kibana 扩展参考edit

Kibana 使用支持以下内容的扩展扩展了 Vega 和 Vega-Lite

  • 自动调整大小
  • 与 Kibana 相匹配的默认主题
  • 使用仪表板中的时间范围和过滤器编写 Elasticsearch 查询
  • [preview] 此功能处于技术预览阶段,可能会在将来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 在 Vega 地图中使用 Elastic 地图服务
  • 其他工具提示样式
  • 高级设置以启用从任何域加载 URL
  • 使用 Kibana 检查器或浏览器控制台进行调试支持
  • (仅限 Vega) 可以更新时间范围和仪表板过滤器的表达式函数
自动调整大小edit

大多数用户希望他们的 Vega 可视化占用所有可用空间,因此与 Vega 示例不同,widthheight 在 Kibana 中不是必需的参数,因为在大多数情况下,您的规范将与默认的 Kibana 设置合并

autosize: {
  type: fit
  contains: padding
}
width: container
height: container

这些默认设置 应用于以下情况

  • 您的规范使用 type=map
  • 您的规范是 Vega-Lite 并且包含一个 facet、row、column、repeat 或 concat 运算符。在这些情况下,提供 widthheight 将影响子级大小。

要手动设置宽度或高度,请设置 autosize: none 并提供确切的像素大小,包括标题、图例和轴的填充。

autosize: none
width: 600
height: 200
padding: {
  top: 20
  bottom: 20
  left: 55
  right: 150
}

要了解更多信息,请阅读有关 Vega autosizeVega-Lite autosize 的内容。

Vega-Lite 中的自动调整大小具有 一些限制,这些限制会影响可视化的高度和宽度,但这些限制在 Vega 中不存在。如果您需要完全控制,请使用 浏览器控制台 VEGA_DEBUG.vega_spec 输出将您的规范转换为 Vega。要禁用这些警告,您可以 在您的规范中添加额外的选项

与 Kibana 相匹配的默认主题edit

Kibana 使用 id 为 elastic 的默认 Vega 颜色方案 注册了一个默认 Vega 颜色方案,并为每个 mark 类型设置了一个默认颜色。通过提供不同的 strokefillcolor(Vega-Lite)值来覆盖它。

在 Vega 中编写 Elasticsearch 查询edit

Kibana 使用对指定为 url 的直接 Elasticsearch 查询的支持扩展了 Vega 数据 元素。

Kibana 无法支持动态加载的数据,否则它将在 Vega 中工作。所有数据都在传递给 Vega 渲染器之前被获取。

要在 Vega 中定义一个 Elasticsearch 查询,请将 url 设置为一个对象。Kibana 解析该对象,寻找允许您的查询与 Kibana 集成的特殊标记。

标记包括以下内容

  • %context%: true: 设置在顶层,并用仪表板中的过滤器替换 query 部分
  • %timefield%: <name>: 设置在顶层,将查询与仪表板时间过滤器集成
  • {%timefilter%: true}: 被具有上限和下限的 Elasticsearch 范围查询替换
  • {%timefilter%: "min" | "max"}: 仅被上限或下限替换
  • {%timefilter: true, shift: -1, unit: 'hour'}: 生成一个过去一小时的时间范围查询
  • {%autointerval%: true}: 被包含自动 Kibana 时间间隔的字符串替换,例如 1h
  • {%autointerval%: 10}: 被一个字符串替换,该字符串大约将时间划分为 10 个范围,允许您影响自动间隔
  • "%dashboard_context-must_clause%": 被包含过滤器的对象替换的字符串
  • "%dashboard_context-filter_clause%": 被包含过滤器的对象替换的字符串
  • "%dashboard_context-must_not_clause%": 被包含过滤器的对象替换的字符串

Vega 支持 interval 参数,该参数在 Elasticsearch 8.0.0 及更高版本中不受支持。要使用间隔,请改用 fixed_intervalcalendar_interval

例如,以下查询计算特定索引中的文档数量

// An object instead of a string for the URL value
// is treated as a context-aware Elasticsearch query.
url: {
  // Specify the time filter.
  %timefield%: @timestamp
  // Apply dashboard context filters when set
  %context%: true

  // Which indexes to search
  index: kibana_sample_data_logs
  // The body element may contain "aggs" and "query" keys
  body: {
    aggs: {
      time_buckets: {
        date_histogram: {
          // Use date histogram aggregation on @timestamp field
          field: @timestamp 
          // interval value will depend on the time filter
          // Use an integer to set approximate bucket count
          interval: { %autointerval%: true }
          // Make sure we get an entire range, even if it has no data
          extended_bounds: {
            min: { %timefilter%: "min" }
            max: { %timefilter%: "max" }
          }
          // Use this for linear (e.g. line, area) graphs
          // Without it, empty buckets will not show up
          min_doc_count: 0
        }
      }
    }
    // Speed up the response by only including aggregation results
    size: 0
  }
}

@timestamp — 过滤时间范围并将其分解为直方图桶。

完整结果包括以下结构

{
  "aggregations": {
    "time_buckets": {
      "buckets": [{
          "key_as_string": "2015-11-30T22:00:00.000Z",
          "key": 1448920800000,
          "doc_count": 28
        }, {
          "key_as_string": "2015-11-30T23:00:00.000Z",
          "key": 1448924400000, 
          "doc_count": 330
        }, ...

"key" — 您可以使用 Vega 日期表达式无需转换的 Unix 时间戳。

对于大多数可视化,您只需要桶值列表。要只关注您需要的数据,请使用 format: {property: "aggregations.time_buckets.buckets"}

使用单个范围和仪表板上下文指定查询。该查询等效于 "%context%": true, "%timefield%": "@timestamp",只是时间范围向后移动了 10 分钟

{
  body: {
    query: {
      bool: {
        must: [
          // This string will be replaced
          // with the auto-generated "MUST" clause
          "%dashboard_context-must_clause%"
          {
            range: {
              // apply timefilter (upper right corner)
              // to the @timestamp variable
              @timestamp: {
                // "%timefilter%" will be replaced with
                // the current values of the time filter
                // (from the upper right corner)
                "%timefilter%": true
                // Only work with %timefilter%
                // Shift current timefilter by 10 units back
                shift: 10
                // week, day (default), hour, minute, second
                unit: minute
              }
            }
          }
        ]
        must_not: [
          // This string will be replaced with
          // the auto-generated "MUST-NOT" clause
          "%dashboard_context-must_not_clause%"
        ]
        filter: [
          // This string will be replaced
          // with the auto-generated "FILTER" clause
          "%dashboard_context-filter_clause%"
        ]
      }
    }
  }
}

当使用 "%context%": true 或为 "%timefield%" 定义一个值时,主体不能包含查询。要自定义 VEGA 规范中的查询(例如,添加额外的过滤器或移动时间过滤器),请定义您的查询并像上面的示例一样使用占位符。占位符将在解析后被仪表板或可视化的实际上下文替换。

"%timefilter%" 也可以用于指定单个最小值或最大值。date_histogram 的 extended_bounds 可以使用两个值设置 - 最小值和最大值。您可以使用 "min": {"%timefilter%": "min"} 而不是硬编码一个值,它将被当前时间范围的开始替换。还支持 shiftunit 值。还可以根据当前选择的范围动态设置 "interval": "interval": {"%autointerval%": 10} 将尝试获取大约 10-15 个数据点(桶)。

访问 Elastic 地图服务文件edit

[preview] 此功能处于技术预览阶段,可能会在将来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 通过相同的机制访问 Elastic 地图服务文件

url: {
  // "type" defaults to "elasticsearch" otherwise
  %type%: emsfile
  // Name of the file, exactly as in https://maps.elastic.co
  name: World Countries
}
// The result is either a topojson file or a geojson file.
// Refer to the Default format for the file at https://maps.elastic.co
// Get its features to use this data source with the "shape" marks
// https://vega.github.io/vega/docs/marks/shape/
// For a topojson file use
format: {type: "topojson", feature: "data"}

// For a geojson file use
format: {property: "features"}

带有地图的 Vegaedit

[preview] 此功能处于技术预览阶段,可能会在将来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 要启用 地图,图形必须在主机配置中指定 type=map

{
  "config": {
    "kibana": {
      "type": "map",

      // Initial map position
      "latitude": 40.7,   // default 0
      "longitude": -74,   // default 0
      "zoom": 7,          // default 2

      // Defaults to 'true', disables the base map layer.
      "mapStyle": false,

      // When 'mapStyle' is 'undefined' or 'true', sets the EMS-layer for the map.
      // May either be: "road_map", "road_map_desaturated", "dark_map".
      // If 'emsTileServiceId' is 'undefined', it falls back to the auto-switch-dark-light behavior.
      "emsTileServiceId": "road_map",

      // default 0
      "minZoom": 5,

      // defaults to the maximum for the given style,
      // or 25 when base is disabled
      "maxZoom": 13,

      // Defaults to 'true', shows +/- buttons to zoom in/out
      "zoomControl": false,

      // Defaults to 'false', disables mouse wheel zoom. If set to
      // 'true', map may zoom unexpectedly while scrolling dashboard
      "scrollWheelZoom": false,

      // When false, repaints on each move frame.
      // Makes the graph slower when moving the map
      "delayRepaint": true, // default true
    }
  },
  /* the rest of Vega JSON */
}

可视化会自动注入一个 "projection",你可以用它来计算所有地理感知标记的位置。此外,你还可以使用 latitudelongitudezoom 信号。这些信号可以在图表中使用,也可以用来更新地图的位置。

[预览] 此功能处于技术预览阶段,可能会在将来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 你可以使用 Vega 数据 元素通过将 url.data 设置为 emsFile 来访问 Elastic Maps Service (EMS) 中的行政边界矢量形状。

  "data": [
    {
      "name": "countries",
      "url": {
        // "type" defaults to "elasticsearch" otherwise
        %type%: emsfile
        // Name of the file, exactly as in the Region map visualization
        name: World Countries
      },
      // The result is a topojson file, get its features to use
      // this data source with the "shape" marks
      // https://vega.github.io/vega/docs/marks/shape/
      "format": {"type": "topojson", "feature": "data"},
    }
  ],
  "marks": [
    {
      "type": "shape",
      "from": {"data": "countries"},
      "transform": [{"type": "geoshape", "projection": "projection"}]
    }
  ]
其他工具提示样式编辑

Kibana 已安装 Vega 工具提示插件,因此可以按照文档中的方式定义工具提示。除此之外,Kibana 还支持一个配置选项来更改工具提示的位置和填充。

{
  config: {
    kibana: {
      tooltips: {
        position: 'top',
        padding: 15,
        textTruncate: true,
      }
    }
  }
}
启用来自任何域的 URL 加载编辑

Vega 可以从任何 URL 加载数据。要启用此功能,请在 kibana.yml 中设置 vis_type_vega.enableExternalUrls: true,然后重启 Kibana。

外部 URL 加载的文件必须允许 CORS。远程 URL 必须包含 Access-Control-Allow-Origin,它允许来自 Kibana URL 的请求。

你可以使用占位符 %timefilter_min%%timefilter_max% 将当前时间范围作为毫秒时间戳添加到外部 URL 中,例如 http://example.com?min=%timefilter_min%

Vega 检查器编辑

使用上下文 检查 工具来深入了解不同的元素。

检查 Elasticsearch 请求编辑

Vega 使用 Elasticsearch 搜索 API 从 Elasticsearch 获取文档和聚合结果。要排查这些请求,请单击 检查,它将显示最近的请求。如果你的规范包含多个请求,你可以使用 视图 下拉菜单在视图之间切换。

vega tutorial inspect requests
Vega 调试编辑

使用 Vega 调试 视图,你可以检查 数据集信号值 运行时数据。

运行时数据是从 运行时范围 中读取的。

vega tutorial inspect data sets

要调试更复杂的规范,请访问 view 变量。有关更多信息,请参阅 Vega 浏览器调试过程

寻求有关 Vega 规范的帮助编辑

由于 Elasticsearch 中数据的动态特性,除非你能共享数据集,否则很难帮助你解决 Vega 规范问题。为此,请单击 检查,选择 Vega 调试 视图,然后选择 规范

vega tutorial getting help

要复制响应,请单击 复制到剪贴板。将复制的数据粘贴到 gist.github.com,可能需要添加 .json 扩展名。使用 [raw] 按钮,并在寻求帮助时共享该按钮。

浏览器调试控制台编辑

[预览] 此功能处于技术预览阶段,可能会在将来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 使用浏览器调试工具(例如,在 Chrome 中使用 F12 或 Ctrl+Shift+J)检查 VEGA_DEBUG 变量

  • view — 访问 Vega View 对象。有关如何在运行时检查数据和信号的信息,请参阅 Vega 调试指南。对于 Vega-Lite,VEGA_DEBUG.view.data('source_0') 获取预转换的数据,而 VEGA_DEBUG.view.data('data_0') 获取编码后的数据。对于 Vega,它使用在 Vega 规范中定义的数据名称。
  • vega_spec — Kibana 修改后的 Vega JSON 图表规范。对于 Vega-Lite,这是 Vega-Lite 编译器的输出。
  • vegalite_spec — 如果这是一个 Vega-Lite 图表,则为 Vega-Lite 编译前的图表 JSON 规范。
(仅限 Vega) 可以更新时间范围和仪表板过滤器的表达式函数编辑

Kibana 已使用这些函数扩展了 Vega 表达式语言。这些函数将触发获取新数据,默认情况下将重置 Vega 信号。要保留信号值,请在 Vega 配置中设置 restoreSignalValuesOnRefresh: true

/**
  * @param {object} query Elastic Query DSL snippet, as used in the query DSL editor
  * @param {string} [index] as defined in Kibana, or default if missing
  * @param {string} Custom label of the filter shown in the filter bar
  */
kibanaAddFilter(query, index, alias)

/**
  * @param {object} query Elastic Query DSL snippet, as used in the query DSL editor
  * @param {string} [index] as defined in Kibana, or default if missing
  */
kibanaRemoveFilter(query, index)

kibanaRemoveAllFilters()

/**
  * Update dashboard time filter to the new values
  * @param {number|string|Date} start
  * @param {number|string|Date} end
  */
kibanaSetTimeFilter(start, end)
其他配置选项编辑
{
  config: {
    kibana: {
      // Placement of the Vega-defined signal bindings.
      // Can be `left`, `right`, `top`, or `bottom` (default).
      controlsLocation: top
      // Can be `vertical` or `horizontal` (default).
      controlsDirection: vertical
      // If true, hides most of Vega and Vega-Lite warnings
      hideWarnings: true
      // Vega renderer to use: `svg` or `canvas` (default)
      renderer: canvas
      // Defaults to 'false', restores Vega signal values on refresh
      restoreSignalValuesOnRefresh: false
    }
  }
}

资源和示例编辑

要详细了解 Vega 和 Vega-Lite,请参阅资源和示例。

Vega 编辑器编辑

Vega 编辑器 包含 Vega 和 Vega-Lite 的示例,但不支持任何 Kibana 特定功能,例如 Elasticsearch 请求和交互式底图。

Vega-Lite 资源编辑
Vega 资源编辑

在 Kibana 中使用示例时,你可能需要修改“数据”部分以使用绝对 URL。例如,将 "url": "data/world-110m.json" 替换为 "url": "https://vega.github.io/editor/data/world-110m.json"