How To Create a Visualization for Nested Objects Templates?

Before I begin, I’d want to express my gratitude to Aditya Nama, without whom I would not have been able to write this blog. You could read his articles here or follow him on Twitter

This tutorial introduces the basics of Vega. We’ll look at a bar chart and deconstruct it into its component elements. After completing the tutorial, you should be ready to start exploring and modifying Vega visualizations.

What is VEGA?

Vega is a visualization grammar, a declarative language for creating, saving, and sharing interactive visualization designs. With Vega, you can describe the visual appearance and interactive behavior of a visualization in a JSON format, and generate web-based views using Canvas or SVG.

Vega provides basic building blocks for a wide variety of visualization designs: data loading and transformation, scales, map projections, axes, legends, and graphical marks such as rectangles, lines, plotting symbols, etc. Interaction techniques can be specified using reactive signals that dynamically modify a visualization in response to input event streams.

A Vega specification defines an interactive visualization in a JSON format. Specifications are parsed by Vega’s JavaScript runtime to generate both static images and interactive web-based views. Vega provides a convenient representation for computational generation of visualizations and can serve as a foundation for new APIs and visual analysis tools.

How to Create Nested Templates

The nested type is a specialized version of the object a data type that allows arrays of objects to be indexed in a way that they can be queried independently of each other.

If you need to index arrays of objects and to maintain the independence of each object in the array, you should use the nested datatype instead of the object datatype. Internally, nested objects index each object in the array as a separate hidden document, meaning that each nested object can be queried independently of the others, with the nested query:

PUT  _template/nested-logs
"index_patterns": [
"settings": {
"number_of_shards": 3
"mappings": {
"properties": {
"httpRequest": {
"properties": {
"headers": {
"type": "nested"
"clientIp": {
"type": "keyword",
"fields": {
"keyword": {
"type": "ip"
"timestamp": {
"format": "epoch_millis",
"type": "date"

After creating the index pattern go to Stack Management in OpenSearch -> Create a new index pattern and select timestamp and click on create Index

Vega Visualization

We’ll now walk through the visualization definition visiting each of these components:

  • Visualization Size
  • Data
  • Transformation
  • Marks

Visualization Size

The first set of top-level properties determine the size of the visualization:

/* Resizing the Visualtization */"autosize": "none",
"width": 500,
"height": 300,
"padding": 45,

The size of the data rectangle, or the region of the chart where data is plotted, is determined by the width and height settings. Axes and legends, for example, may require more space.
The padding specifies the distance between the chart content and the view’s border. The autosize attribute specifies the method for determining the final chart size:

  • "pad"The default setting, “pad,” adds extra space to accommodate all graphical markers, such as axes and legends. The size of the data rectangle remains the same. The view component may get exceedingly huge if any markers are placed at extreme points outside the data rectangle!
  • "fit"tries to fit the full chart (data rectangle, axes, legends, but not padding) within the width and height parameters. To accommodate axes and legends, Vega will decrease the data rectangle. Clipping may occur in specific instances, such as when a legend is exceedingly tall.
  • "none"Automatic sizing is disabled when the value “none” is used. The width and height of the chart, plus padding, constitute the final chart size. There are no changes to accommodate axes, legends, or other features.

For more details, see the top-level specification documentation.


The data property is an array of data definitions. Each entry in the data array must be an object with a unique name for the data set. As shown here, data can be directly defined inline using the values property. In this example, we have an array of data objects with fields named category (a string label) and amount (a number).

In Vega specifications, data can be:

  • loaded from the web by using the url property (including JSON and CSV files),
  • derived from a previously defined data set using the source property, or
  • left undefined and dynamically set when the visualization is constructed.

Only one of the values, url or source properties may be defined.

Data sets in Vega can be modified using a collection of transforms such as filtering, aggregation, and layout operations. Transformations are specified using the transform property, which takes an array of transform definitions. For more details, see the data and transform documentation.

/* adding a Nested Documentation Data */  "data": {
"url": {
"%context%": true,
"%timefield%": "timestamp",
"index": "test",
"body": {
"size": 0,
"aggs": {
"a": {
"nested": {"path": "headers"},
"aggs": {
"b": {
"filter": {
"bool": {
"filter": [
{"term": {"": "Category"}}
"aggs": {"c": {"terms": {"field": "headers.value.keyword"}}}
"format": {"type": "json", "property": "aggregations.a.b.c.buckets"}


Transforms process a data stream to filter data, calculate new fields, or derive new data streams. Transforms are typically specified within the transform array of a data definition. In addition, transforms that do not filter or generate new data objects can be used within the transform array of a mark definition to specify post-encoding transforms.

The following example defines a new data set with transforms to filter values and then compute a stacked layout (e.g., for a stacked bar chart):

For more details, see the transform documentation.

/* adding limitation only less than 10 */
"transform": [
{"window": [{"op": "count", "as": "count"}]},
{"filter": "datum.count <= 10"}


Marks are the primary elements of a visualization: they are graphical primitives whose properties (such as position, size, shape, and color) can be used to visually encode data. Vega provides a set of marks that serve as building blocks that can be combined to form rich visualizations. Here, we simply use rectangles (rect marks) to construct a bar chart.

Every mark must have a type property, which determines which kind of mark (rect, area, line, symbol, etc.) to use. Next, we must specify the data to be visualized using the from property. In most cases, one simply needs to reference a named data set defined in the top-level data property. If no from property is provided, a single mark instance will be created. For more details, see the marks documentation.

/* adding a Bar Chart */"mark": {"type": "bar", "cornerRadiusEnd": 8},
"encoding": {
"x": {"field": "key", "type": "ordinal", "title": "Category", "sort": {"field": "doc_count", "order": "descending" },"axis": {"labelAngle": 0}},
"y": {"field": "doc_count", "type": "quantitative", "title": "Number of Requests"}

How To Create A Visualization out of the nested document?

I have nested documents in elasticsearch. Anyways using vega, for the first time, I can query nested documents in Kibana and produce visualizations on a dashboard. Previously we had to run our nested aggregations then push the results into elastic for visualizations in Kibana. Below is a sanitized example of a simple vega-lite visualization I am using.



Siddhanth Dwivedi |Security Engineer |Help in building apps more secure|

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store