Using Vega

Vega and Vega-Lite are open-source, declarative language visualization tools that you can use to create custom data visualizations with your OpenSearch data and Vega Data. These tools are ideal for advanced users comfortable with writing OpenSearch queries directly. Enable the vis_type_vega plugin in your opensearch_dashboards.yml file to write your Vega specifications in either JSON or HJSON format or to specify one or more OpenSearch queries within your Vega specification. By default, the plugin is set to true. The configuration is shown in the following example. For configuration details, refer to the vis_type_vega README.

  1. vis_type_vega.enabled: true

The following image shows a custom Vega map created in OpenSearch.

Map created using Vega visualization in OpenSearch Dashboards

Querying from multiple data sources

If you have configured multiple data sources in OpenSearch Dashboards, you can use Vega to query those data sources. Within your Vega specification, add the data_source_name field under the url property to target a specific data source by name. By default, queries use data from the local cluster. You can assign individual data_source_name values to each OpenSearch query within your Vega specification. This allows you to query multiple indexes across different data sources in a single visualization.

The following is an example Vega specification with Demo US Cluster as the specified data_source_name:

  1. {
  2. $schema: https://vega.github.io/schema/vega/v5.json
  3. config: {
  4. kibana: {type: "map", latitude: 25, longitude: -70, zoom: 3}
  5. }
  6. data: [
  7. {
  8. name: table
  9. url: {
  10. index: opensearch_dashboards_sample_data_flights
  11. // This OpenSearchQuery will query from the Demo US Cluster datasource
  12. data_source_name: Demo US Cluster
  13. %context%: true
  14. // Uncomment to enable time filtering
  15. // %timefield%: timestamp
  16. body: {
  17. size: 0
  18. aggs: {
  19. origins: {
  20. terms: {field: "OriginAirportID", size: 10000}
  21. aggs: {
  22. originLocation: {
  23. top_hits: {
  24. size: 1
  25. _source: {
  26. includes: ["OriginLocation", "Origin"]
  27. }
  28. }
  29. }
  30. distinations: {
  31. terms: {field: "DestAirportID", size: 10000}
  32. aggs: {
  33. destLocation: {
  34. top_hits: {
  35. size: 1
  36. _source: {
  37. includes: ["DestLocation"]
  38. }
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. }
  46. }
  47. }
  48. format: {property: "aggregations.origins.buckets"}
  49. transform: [
  50. {
  51. type: geopoint
  52. projection: projection
  53. fields: [
  54. originLocation.hits.hits[0]._source.OriginLocation.lon
  55. originLocation.hits.hits[0]._source.OriginLocation.lat
  56. ]
  57. }
  58. ]
  59. }
  60. {
  61. name: selectedDatum
  62. on: [
  63. {trigger: "!selected", remove: true}
  64. {trigger: "selected", insert: "selected"}
  65. ]
  66. }
  67. ]
  68. signals: [
  69. {
  70. name: selected
  71. value: null
  72. on: [
  73. {events: "@airport:mouseover", update: "datum"}
  74. {events: "@airport:mouseout", update: "null"}
  75. ]
  76. }
  77. ]
  78. scales: [
  79. {
  80. name: airportSize
  81. type: linear
  82. domain: {data: "table", field: "doc_count"}
  83. range: [
  84. {signal: "zoom*zoom*0.2+1"}
  85. {signal: "zoom*zoom*10+1"}
  86. ]
  87. }
  88. ]
  89. marks: [
  90. {
  91. type: group
  92. from: {
  93. facet: {
  94. name: facetedDatum
  95. data: selectedDatum
  96. field: distinations.buckets
  97. }
  98. }
  99. data: [
  100. {
  101. name: facetDatumElems
  102. source: facetedDatum
  103. transform: [
  104. {
  105. type: geopoint
  106. projection: projection
  107. fields: [
  108. destLocation.hits.hits[0]._source.DestLocation.lon
  109. destLocation.hits.hits[0]._source.DestLocation.lat
  110. ]
  111. }
  112. {type: "formula", expr: "{x:parent.x, y:parent.y}", as: "source"}
  113. {type: "formula", expr: "{x:datum.x, y:datum.y}", as: "target"}
  114. {type: "linkpath", shape: "diagonal"}
  115. ]
  116. }
  117. ]
  118. scales: [
  119. {
  120. name: lineThickness
  121. type: log
  122. clamp: true
  123. range: [1, 8]
  124. }
  125. {
  126. name: lineOpacity
  127. type: log
  128. clamp: true
  129. range: [0.2, 0.8]
  130. }
  131. ]
  132. marks: [
  133. {
  134. from: {data: "facetDatumElems"}
  135. type: path
  136. interactive: false
  137. encode: {
  138. update: {
  139. path: {field: "path"}
  140. stroke: {value: "black"}
  141. strokeWidth: {scale: "lineThickness", field: "doc_count"}
  142. strokeOpacity: {scale: "lineOpacity", field: "doc_count"}
  143. }
  144. }
  145. }
  146. ]
  147. }
  148. {
  149. name: airport
  150. type: symbol
  151. from: {data: "table"}
  152. encode: {
  153. update: {
  154. size: {scale: "airportSize", field: "doc_count"}
  155. xc: {signal: "datum.x"}
  156. yc: {signal: "datum.y"}
  157. tooltip: {
  158. signal: "{title: datum.originLocation.hits.hits[0]._source.Origin + ' (' + datum.key + ')', connnections: length(datum.distinations.buckets), flights: datum.doc_count}"
  159. }
  160. }
  161. }
  162. }
  163. ]
  164. }

copy