mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Transformers: Support inner vs outer join (#53913)
This commit is contained in:
parent
1766ea9fdf
commit
1d4e01f8ba
638
devenv/dev-dashboards/transforms/join-by-field.json
Normal file
638
devenv/dev-dashboards/transforms/join-by-field.json
Normal file
@ -0,0 +1,638 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"target": {
|
||||||
|
"limit": 100,
|
||||||
|
"matchAny": false,
|
||||||
|
"tags": [],
|
||||||
|
"type": "dashboard"
|
||||||
|
},
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": 1351,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
|
"panels": [],
|
||||||
|
"title": "Join by time",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 0,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 11,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"refId": "A",
|
||||||
|
"scenarioId": "random_walk",
|
||||||
|
"seriesCount": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Timeseries data",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 13,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 11,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Same data (as a table)",
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 5,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 9
|
||||||
|
},
|
||||||
|
"id": 16,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 11,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "OUTER join on time (default)",
|
||||||
|
"transformations": [
|
||||||
|
{
|
||||||
|
"id": "joinByField",
|
||||||
|
"options": {}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 14
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"panels": [],
|
||||||
|
"title": "Join by string field",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 15
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"frameIndex": 0,
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"csvContent": "OrderID,CustomerID,Time\n100,A,10000\n101,B,20000\n102,C,30000",
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"refId": "Orders",
|
||||||
|
"scenarioId": "csv_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"csvContent": "CustomerID,Name,Country\nA,Customer A,USA\nB,Customer B,Germany\nC,Customer C,Spain\nD,Customer D,Canada",
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"hide": false,
|
||||||
|
"refId": "Customers",
|
||||||
|
"scenarioId": "csv_content"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Orders",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 15
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"frameIndex": 1,
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 2,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Customers",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byName",
|
||||||
|
"options": "CustomerID"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "custom.width",
|
||||||
|
"value": 101
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byName",
|
||||||
|
"options": "OrderID"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "custom.width",
|
||||||
|
"value": 89
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 23
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"frameIndex": 0,
|
||||||
|
"showHeader": true,
|
||||||
|
"sortBy": []
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 2,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "OUTER join on CustomerID (keeps missing values)",
|
||||||
|
"transformations": [
|
||||||
|
{
|
||||||
|
"id": "joinByField",
|
||||||
|
"options": {
|
||||||
|
"byField": "CustomerID",
|
||||||
|
"mode": "outer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byName",
|
||||||
|
"options": "CustomerID"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "custom.width",
|
||||||
|
"value": 101
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byName",
|
||||||
|
"options": "OrderID"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "custom.width",
|
||||||
|
"value": 89
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 23
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"frameIndex": 0,
|
||||||
|
"showHeader": true,
|
||||||
|
"sortBy": []
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 2,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "INNER join on CustomerID ",
|
||||||
|
"transformations": [
|
||||||
|
{
|
||||||
|
"id": "joinByField",
|
||||||
|
"options": {
|
||||||
|
"byField": "CustomerID",
|
||||||
|
"mode": "inner"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schemaVersion": 37,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [
|
||||||
|
"gdev",
|
||||||
|
"transform"
|
||||||
|
],
|
||||||
|
"templating": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "Join by field",
|
||||||
|
"uid": "gw0K4rmVz",
|
||||||
|
"version": 6,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
358
devenv/dev-dashboards/transforms/join-by-labels.json
Normal file
358
devenv/dev-dashboards/transforms/join-by-labels.json
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"target": {
|
||||||
|
"limit": 100,
|
||||||
|
"matchAny": false,
|
||||||
|
"tags": [],
|
||||||
|
"type": "dashboard"
|
||||||
|
},
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": 1342,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"maxDataPoints": 1,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "none",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"labels": "site=A,measure=speed,state=CA",
|
||||||
|
"refId": "A",
|
||||||
|
"scenarioId": "random_walk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"hide": false,
|
||||||
|
"labels": "site=B,measure=speed,state=OR",
|
||||||
|
"refId": "B",
|
||||||
|
"scenarioId": "random_walk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"hide": false,
|
||||||
|
"labels": "site=B,measure=temp",
|
||||||
|
"refId": "C",
|
||||||
|
"scenarioId": "random_walk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "testdata",
|
||||||
|
"uid": "PD8C576611E62080A"
|
||||||
|
},
|
||||||
|
"hide": false,
|
||||||
|
"labels": "site=A,measure=temp",
|
||||||
|
"refId": "D",
|
||||||
|
"scenarioId": "random_walk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Labeled values",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"maxDataPoints": 1,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"frameIndex": 2,
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 2,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Same values... in a table",
|
||||||
|
"transformations": [],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 10
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"maxDataPoints": 1,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 2,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Join by site",
|
||||||
|
"transformations": [
|
||||||
|
{
|
||||||
|
"id": "joinByLabels",
|
||||||
|
"options": {
|
||||||
|
"join": [
|
||||||
|
"site"
|
||||||
|
],
|
||||||
|
"value": "measure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"align": "auto",
|
||||||
|
"displayMode": "auto",
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 10
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"maxDataPoints": 1,
|
||||||
|
"options": {
|
||||||
|
"footer": {
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "9.2.0-pre",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "-- Dashboard --"
|
||||||
|
},
|
||||||
|
"panelId": 2,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Join on all labels",
|
||||||
|
"transformations": [
|
||||||
|
{
|
||||||
|
"id": "joinByLabels",
|
||||||
|
"options": {
|
||||||
|
"value": "measure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schemaVersion": 37,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [
|
||||||
|
"gdev",
|
||||||
|
"transform"
|
||||||
|
],
|
||||||
|
"templating": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "Join by labels",
|
||||||
|
"uid": "FVl-9CR4z",
|
||||||
|
"version": 10,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
@ -322,15 +322,77 @@ We would then get :
|
|||||||
| server 2 | 88.6 | 90 | 2020-07-07 10:32:20 | Overload |
|
| server 2 | 88.6 | 90 | 2020-07-07 10:32:20 | Overload |
|
||||||
| server 3 | 59.6 | 62 | 2020-07-07 11:34:20 | OK |
|
| server 3 | 59.6 | 62 | 2020-07-07 11:34:20 | OK |
|
||||||
|
|
||||||
This transformation allows you to extract some key information out of your time series and display them in a convenient way.
|
This transformation enables you to extract key information from your time series and display it in a convenient way.
|
||||||
|
|
||||||
### Join by field (outer join)
|
### Join by field
|
||||||
|
|
||||||
Use this transformation to join multiple time series from a result set by field.
|
Use this transformation to join multiple results into a single table. This is especially useful for converting multiple
|
||||||
|
time series results into a single wide table with a shared time field.
|
||||||
|
|
||||||
This transformation is especially useful if you want to combine queries so that you can calculate results from the fields.
|
#### Inner join
|
||||||
|
|
||||||
In the example below, I have a template query displaying time series data from multiple servers in a table visualization. I can only view the results of one query at a time.
|
An inner join merges data from multiple tables where all tables share the same value from the selected field. This type of join excludes
|
||||||
|
data where values do not match in every result.
|
||||||
|
|
||||||
|
Use this transformation to combine the results from multiple queries (combining on a passed join field or the first time column) into one result, and drop rows where a successful join cannot occur.
|
||||||
|
|
||||||
|
In the following example, two queries return table data. It is visualized as two separate tables before applying the inner join transformation.
|
||||||
|
|
||||||
|
Query A:
|
||||||
|
|
||||||
|
| Time | Job | Uptime |
|
||||||
|
| ------------------- | ------- | --------- |
|
||||||
|
| 2020-07-07 11:34:20 | node | 25260122 |
|
||||||
|
| 2020-07-07 11:24:20 | postgre | 123001233 |
|
||||||
|
| 2020-07-07 11:14:20 | postgre | 345001233 |
|
||||||
|
|
||||||
|
Query B:
|
||||||
|
|
||||||
|
| Time | Server | Errors |
|
||||||
|
| ------------------- | -------- | ------ |
|
||||||
|
| 2020-07-07 11:34:20 | server 1 | 15 |
|
||||||
|
| 2020-07-07 11:24:20 | server 2 | 5 |
|
||||||
|
| 2020-07-07 11:04:20 | server 3 | 10 |
|
||||||
|
|
||||||
|
The result after applying the inner join transformation looks like the following:
|
||||||
|
|
||||||
|
| Time | Job | Uptime | Server | Errors |
|
||||||
|
| ------------------- | ------- | --------- | -------- | ------ |
|
||||||
|
| 2020-07-07 11:34:20 | node | 25260122 | server 1 | 15 |
|
||||||
|
| 2020-07-07 11:24:20 | postgre | 123001233 | server 2 | 5 |
|
||||||
|
|
||||||
|
#### Outer join
|
||||||
|
|
||||||
|
An outer join includes all data from an inner join and rows where values do not match in every input.
|
||||||
|
|
||||||
|
Use this transformation to combine the results from multiple queries (combining on a passed join field or the first time column) into one result, and drop rows where a successful join cannot occur - performing an inner join.
|
||||||
|
|
||||||
|
In the following example, two queries return table data. It is visualized as two tables before applying the inner join transformation.
|
||||||
|
|
||||||
|
Query A:
|
||||||
|
|
||||||
|
| Time | Job | Uptime |
|
||||||
|
| ------------------- | ------- | --------- |
|
||||||
|
| 2020-07-07 11:34:20 | node | 25260122 |
|
||||||
|
| 2020-07-07 11:24:20 | postgre | 123001233 |
|
||||||
|
| 2020-07-07 11:14:20 | postgre | 345001233 |
|
||||||
|
|
||||||
|
Query B:
|
||||||
|
|
||||||
|
| Time | Server | Errors |
|
||||||
|
| ------------------- | -------- | ------ |
|
||||||
|
| 2020-07-07 11:34:20 | server 1 | 15 |
|
||||||
|
| 2020-07-07 11:24:20 | server 2 | 5 |
|
||||||
|
| 2020-07-07 11:04:20 | server 3 | 10 |
|
||||||
|
|
||||||
|
The result after applying the inner join transformation looks like the following:
|
||||||
|
|
||||||
|
| Time | Job | Uptime | Server | Errors |
|
||||||
|
| ------------------- | ------- | --------- | -------- | ------ |
|
||||||
|
| 2020-07-07 11:34:20 | node | 25260122 | server 1 | 15 |
|
||||||
|
| 2020-07-07 11:24:20 | postgre | 123001233 | server 2 | 5 |
|
||||||
|
|
||||||
|
In the following example, a template query displays time series data from multiple servers in a table visualization. The results of only one query can be viewed at a time.
|
||||||
|
|
||||||
{{< figure src="/static/img/docs/transformations/join-fields-before-7-0.png" class="docs-image--no-shadow" max-width= "1100px" >}}
|
{{< figure src="/static/img/docs/transformations/join-fields-before-7-0.png" class="docs-image--no-shadow" max-width= "1100px" >}}
|
||||||
|
|
||||||
@ -643,32 +705,3 @@ Here is the result after adding a Limit transformation with a value of '3':
|
|||||||
| 2020-07-07 11:34:20 | Temperature | 25 |
|
| 2020-07-07 11:34:20 | Temperature | 25 |
|
||||||
| 2020-07-07 11:34:20 | Humidity | 22 |
|
| 2020-07-07 11:34:20 | Humidity | 22 |
|
||||||
| 2020-07-07 10:32:20 | Humidity | 29 |
|
| 2020-07-07 10:32:20 | Humidity | 29 |
|
||||||
|
|
||||||
### Join by field (Inner join)
|
|
||||||
|
|
||||||
Use this transformation to combine the results from multiple queries (combining on a passed join field or the first time column) into one single result and drop rows where a successful join isn't able to occur - performing an inner join.
|
|
||||||
|
|
||||||
In the example below, we have two queries returning table data. It is visualized as two separate tables before applying the inner join transformation.
|
|
||||||
|
|
||||||
Query A:
|
|
||||||
|
|
||||||
| Time | Job | Uptime |
|
|
||||||
| ------------------- | ------- | --------- |
|
|
||||||
| 2020-07-07 11:34:20 | node | 25260122 |
|
|
||||||
| 2020-07-07 11:24:20 | postgre | 123001233 |
|
|
||||||
| 2020-07-07 11:14:20 | postgre | 345001233 |
|
|
||||||
|
|
||||||
Query B:
|
|
||||||
|
|
||||||
| Time | Server | Errors |
|
|
||||||
| ------------------- | -------- | ------ |
|
|
||||||
| 2020-07-07 11:34:20 | server 1 | 15 |
|
|
||||||
| 2020-07-07 11:24:20 | server 2 | 5 |
|
|
||||||
| 2020-07-07 11:04:20 | server 3 | 10 |
|
|
||||||
|
|
||||||
Result after applying the inner join transformation:
|
|
||||||
|
|
||||||
| Time | Job | Uptime | Server | Errors |
|
|
||||||
| ------------------- | ------- | --------- | -------- | ------ |
|
|
||||||
| 2020-07-07 11:34:20 | node | 25260122 | server 1 | 15 |
|
|
||||||
| 2020-07-07 11:24:20 | postgre | 123001233 | server 2 | 5 |
|
|
||||||
|
@ -9,6 +9,7 @@ import { filterByValueTransformer } from './transformers/filterByValue';
|
|||||||
import { groupByTransformer } from './transformers/groupBy';
|
import { groupByTransformer } from './transformers/groupBy';
|
||||||
import { groupingToMatrixTransformer } from './transformers/groupingToMatrix';
|
import { groupingToMatrixTransformer } from './transformers/groupingToMatrix';
|
||||||
import { histogramTransformer } from './transformers/histogram';
|
import { histogramTransformer } from './transformers/histogram';
|
||||||
|
import { joinByFieldTransformer } from './transformers/joinByField';
|
||||||
import { labelsToFieldsTransformer } from './transformers/labelsToFields';
|
import { labelsToFieldsTransformer } from './transformers/labelsToFields';
|
||||||
import { limitTransformer } from './transformers/limit';
|
import { limitTransformer } from './transformers/limit';
|
||||||
import { mergeTransformer } from './transformers/merge';
|
import { mergeTransformer } from './transformers/merge';
|
||||||
@ -18,7 +19,6 @@ import { organizeFieldsTransformer } from './transformers/organize';
|
|||||||
import { reduceTransformer } from './transformers/reduce';
|
import { reduceTransformer } from './transformers/reduce';
|
||||||
import { renameFieldsTransformer } from './transformers/rename';
|
import { renameFieldsTransformer } from './transformers/rename';
|
||||||
import { renameByRegexTransformer } from './transformers/renameByRegex';
|
import { renameByRegexTransformer } from './transformers/renameByRegex';
|
||||||
import { seriesToColumnsTransformer } from './transformers/seriesToColumns';
|
|
||||||
import { seriesToRowsTransformer } from './transformers/seriesToRows';
|
import { seriesToRowsTransformer } from './transformers/seriesToRows';
|
||||||
import { sortByTransformer } from './transformers/sortBy';
|
import { sortByTransformer } from './transformers/sortBy';
|
||||||
|
|
||||||
@ -34,7 +34,9 @@ export const standardTransformers = {
|
|||||||
reduceTransformer,
|
reduceTransformer,
|
||||||
concatenateTransformer,
|
concatenateTransformer,
|
||||||
calculateFieldTransformer,
|
calculateFieldTransformer,
|
||||||
seriesToColumnsTransformer,
|
joinByFieldTransformer,
|
||||||
|
/** @deprecated */
|
||||||
|
seriesToColumnsTransformer: joinByFieldTransformer,
|
||||||
seriesToRowsTransformer,
|
seriesToRowsTransformer,
|
||||||
renameFieldsTransformer,
|
renameFieldsTransformer,
|
||||||
labelsToFieldsTransformer,
|
labelsToFieldsTransformer,
|
||||||
|
@ -5,7 +5,7 @@ import { transformDataFrame } from '../transformDataFrame';
|
|||||||
|
|
||||||
import { ensureColumnsTransformer } from './ensureColumns';
|
import { ensureColumnsTransformer } from './ensureColumns';
|
||||||
import { DataTransformerID } from './ids';
|
import { DataTransformerID } from './ids';
|
||||||
import { seriesToColumnsTransformer } from './seriesToColumns';
|
import { joinByFieldTransformer } from './joinByField';
|
||||||
|
|
||||||
const seriesA = toDataFrame({
|
const seriesA = toDataFrame({
|
||||||
fields: [
|
fields: [
|
||||||
@ -33,7 +33,7 @@ const seriesNoTime = toDataFrame({
|
|||||||
|
|
||||||
describe('ensureColumns transformer', () => {
|
describe('ensureColumns transformer', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
mockTransformationsRegistry([ensureColumnsTransformer, seriesToColumnsTransformer]);
|
mockTransformationsRegistry([ensureColumnsTransformer, joinByFieldTransformer]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will transform to columns if time field exists and multiple frames', async () => {
|
it('will transform to columns if time field exists and multiple frames', async () => {
|
||||||
|
@ -5,7 +5,7 @@ import { DataFrame } from '../../types/dataFrame';
|
|||||||
import { SynchronousDataTransformerInfo } from '../../types/transformations';
|
import { SynchronousDataTransformerInfo } from '../../types/transformations';
|
||||||
|
|
||||||
import { DataTransformerID } from './ids';
|
import { DataTransformerID } from './ids';
|
||||||
import { seriesToColumnsTransformer } from './seriesToColumns';
|
import { joinByFieldTransformer } from './joinByField';
|
||||||
|
|
||||||
export const ensureColumnsTransformer: SynchronousDataTransformerInfo = {
|
export const ensureColumnsTransformer: SynchronousDataTransformerInfo = {
|
||||||
id: DataTransformerID.ensureColumns,
|
id: DataTransformerID.ensureColumns,
|
||||||
@ -19,7 +19,7 @@ export const ensureColumnsTransformer: SynchronousDataTransformerInfo = {
|
|||||||
const timeFieldName = findConsistentTimeFieldName(frames);
|
const timeFieldName = findConsistentTimeFieldName(frames);
|
||||||
|
|
||||||
if (frames.length > 1 && timeFieldName) {
|
if (frames.length > 1 && timeFieldName) {
|
||||||
return seriesToColumnsTransformer.transformer({
|
return joinByFieldTransformer.transformer({
|
||||||
byField: timeFieldName,
|
byField: timeFieldName,
|
||||||
})(frames);
|
})(frames);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
export enum DataTransformerID {
|
export enum DataTransformerID {
|
||||||
// join = 'join', // Pick a field and merge all series based on that field
|
|
||||||
append = 'append',
|
append = 'append',
|
||||||
// rotate = 'rotate', // Columns to rows
|
// rotate = 'rotate', // Columns to rows
|
||||||
reduce = 'reduce',
|
reduce = 'reduce',
|
||||||
@ -7,6 +6,7 @@ export enum DataTransformerID {
|
|||||||
organize = 'organize',
|
organize = 'organize',
|
||||||
rename = 'rename',
|
rename = 'rename',
|
||||||
calculateField = 'calculateField',
|
calculateField = 'calculateField',
|
||||||
|
/** @deprecated use joinByField */
|
||||||
seriesToColumns = 'seriesToColumns',
|
seriesToColumns = 'seriesToColumns',
|
||||||
seriesToRows = 'seriesToRows',
|
seriesToRows = 'seriesToRows',
|
||||||
merge = 'merge',
|
merge = 'merge',
|
||||||
@ -30,6 +30,7 @@ export enum DataTransformerID {
|
|||||||
fieldLookup = 'fieldLookup',
|
fieldLookup = 'fieldLookup',
|
||||||
heatmap = 'heatmap',
|
heatmap = 'heatmap',
|
||||||
spatial = 'spatial',
|
spatial = 'spatial',
|
||||||
|
joinByField = 'joinByField',
|
||||||
joinByLabels = 'joinByLabels',
|
joinByLabels = 'joinByLabels',
|
||||||
extractFields = 'extractFields',
|
extractFields = 'extractFields',
|
||||||
groupingToMatrix = 'groupingToMatrix',
|
groupingToMatrix = 'groupingToMatrix',
|
||||||
|
@ -5,11 +5,11 @@ import { ArrayVector } from '../../vector';
|
|||||||
import { transformDataFrame } from '../transformDataFrame';
|
import { transformDataFrame } from '../transformDataFrame';
|
||||||
|
|
||||||
import { DataTransformerID } from './ids';
|
import { DataTransformerID } from './ids';
|
||||||
import { JoinMode, SeriesToColumnsOptions, seriesToColumnsTransformer } from './seriesToColumns';
|
import { JoinMode, JoinByFieldOptions, joinByFieldTransformer } from './joinByField';
|
||||||
|
|
||||||
describe('SeriesToColumns Transformer', () => {
|
describe('JOIN Transformer', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
mockTransformationsRegistry([seriesToColumnsTransformer]);
|
mockTransformationsRegistry([joinByFieldTransformer]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('outer join', () => {
|
describe('outer join', () => {
|
||||||
@ -32,7 +32,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('joins by time field', async () => {
|
it('joins by time field', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -134,7 +134,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('joins by temperature field', async () => {
|
it('joins by temperature field', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'temperature',
|
byField: 'temperature',
|
||||||
@ -250,7 +250,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('joins by time field in reverse order', async () => {
|
it('joins by time field in reverse order', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -375,7 +375,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('when dataframe and field share the same name then use the field name', async () => {
|
it('when dataframe and field share the same name then use the field name', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -438,7 +438,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('joins if fields are missing', async () => {
|
it('joins if fields are missing', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -516,7 +516,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('handles duplicate field name', async () => {
|
it('handles duplicate field name', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -597,7 +597,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('inner joins by time field', async () => {
|
it('inner joins by time field', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -678,7 +678,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('inner joins by temperature field', async () => {
|
it('inner joins by temperature field', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'temperature',
|
byField: 'temperature',
|
||||||
@ -763,7 +763,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('inner joins by time field in reverse order', async () => {
|
it('inner joins by time field in reverse order', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -867,7 +867,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('when dataframe and field share the same name then use the field name', async () => {
|
it('when dataframe and field share the same name then use the field name', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -931,7 +931,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('joins if fields are missing', async () => {
|
it('joins if fields are missing', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
||||||
@ -1010,7 +1010,7 @@ describe('SeriesToColumns Transformer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('handles duplicate field name', async () => {
|
it('handles duplicate field name', async () => {
|
||||||
const cfg: DataTransformerConfig<SeriesToColumnsOptions> = {
|
const cfg: DataTransformerConfig<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.seriesToColumns,
|
||||||
options: {
|
options: {
|
||||||
byField: 'time',
|
byField: 'time',
|
@ -12,23 +12,25 @@ export enum JoinMode {
|
|||||||
inner = 'inner',
|
inner = 'inner',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SeriesToColumnsOptions {
|
export interface JoinByFieldOptions {
|
||||||
byField?: string; // empty will pick the field automatically
|
byField?: string; // empty will pick the field automatically
|
||||||
mode?: JoinMode;
|
mode?: JoinMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const seriesToColumnsTransformer: SynchronousDataTransformerInfo<SeriesToColumnsOptions> = {
|
export const joinByFieldTransformer: SynchronousDataTransformerInfo<JoinByFieldOptions> = {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.joinByField,
|
||||||
name: 'Series as columns', // Called 'Outer join' in the UI!
|
aliasIds: [DataTransformerID.seriesToColumns],
|
||||||
description: 'Groups series by field and returns values as columns',
|
name: 'Join by field',
|
||||||
|
description:
|
||||||
|
'Combine rows from two or more tables, based on a related field between them. This can be used to outer join multiple time series on the _time_ field to show many time series in one table.',
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
byField: undefined, // DEFAULT_KEY_FIELD,
|
byField: undefined, // DEFAULT_KEY_FIELD,
|
||||||
mode: JoinMode.outer,
|
mode: JoinMode.outer,
|
||||||
},
|
},
|
||||||
|
|
||||||
operator: (options) => (source) => source.pipe(map((data) => seriesToColumnsTransformer.transformer(options)(data))),
|
operator: (options) => (source) => source.pipe(map((data) => joinByFieldTransformer.transformer(options)(data))),
|
||||||
|
|
||||||
transformer: (options: SeriesToColumnsOptions) => {
|
transformer: (options: JoinByFieldOptions) => {
|
||||||
let joinBy: FieldMatcher | undefined = undefined;
|
let joinBy: FieldMatcher | undefined = undefined;
|
||||||
return (data: DataFrame[]) => {
|
return (data: DataFrame[]) => {
|
||||||
if (data.length > 1) {
|
if (data.length > 1) {
|
@ -4,8 +4,8 @@ import { mockTransformationsRegistry } from '../../utils/tests/mockTransformatio
|
|||||||
import { ArrayVector } from '../../vector';
|
import { ArrayVector } from '../../vector';
|
||||||
|
|
||||||
import { calculateFieldTransformer } from './calculateField';
|
import { calculateFieldTransformer } from './calculateField';
|
||||||
|
import { JoinMode } from './joinByField';
|
||||||
import { isLikelyAscendingVector, joinDataFrames } from './joinDataFrames';
|
import { isLikelyAscendingVector, joinDataFrames } from './joinDataFrames';
|
||||||
import { JoinMode } from './seriesToColumns';
|
|
||||||
|
|
||||||
describe('align frames', () => {
|
describe('align frames', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
@ -6,7 +6,7 @@ import { ArrayVector } from '../../vector';
|
|||||||
import { fieldMatchers } from '../matchers';
|
import { fieldMatchers } from '../matchers';
|
||||||
import { FieldMatcherID } from '../matchers/ids';
|
import { FieldMatcherID } from '../matchers/ids';
|
||||||
|
|
||||||
import { JoinMode } from './seriesToColumns';
|
import { JoinMode } from './joinByField';
|
||||||
|
|
||||||
export function pickBestJoinField(data: DataFrame[]): FieldMatcher {
|
export function pickBestJoinField(data: DataFrame[]): FieldMatcher {
|
||||||
const { timeField } = getTimeField(data[0]);
|
const { timeField } = getTimeField(data[0]);
|
||||||
@ -34,7 +34,7 @@ export function pickBestJoinField(data: DataFrame[]): FieldMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @alpha
|
* @internal
|
||||||
*/
|
*/
|
||||||
export interface JoinOptions {
|
export interface JoinOptions {
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,7 @@ export const mockTransformationsRegistry = (transformers: Array<DataTransformerI
|
|||||||
return transformers.map((t) => {
|
return transformers.map((t) => {
|
||||||
return {
|
return {
|
||||||
id: t.id,
|
id: t.id,
|
||||||
|
aliasIds: t.aliasIds,
|
||||||
name: t.name,
|
name: t.name,
|
||||||
transformation: t,
|
transformation: t,
|
||||||
description: t.description,
|
description: t.description,
|
||||||
|
@ -109,7 +109,7 @@ export const decorateWithTableResult = (data: ExplorePanelData): Observable<Expl
|
|||||||
// non timeseries or some mix of data we are not trying to join on anything and just try to merge them in
|
// non timeseries or some mix of data we are not trying to join on anything and just try to merge them in
|
||||||
// single table, which may not make sense in most cases, but it's up to the user to query something sensible.
|
// single table, which may not make sense in most cases, but it's up to the user to query something sensible.
|
||||||
const transformer = hasOnlyTimeseries
|
const transformer = hasOnlyTimeseries
|
||||||
? of(data.tableFrames).pipe(standardTransformers.seriesToColumnsTransformer.operator({}))
|
? of(data.tableFrames).pipe(standardTransformers.joinByFieldTransformer.operator({}))
|
||||||
: of(data.tableFrames).pipe(standardTransformers.mergeTransformer.operator({}));
|
: of(data.tableFrames).pipe(standardTransformers.mergeTransformer.operator({}));
|
||||||
|
|
||||||
return transformer.pipe(
|
return transformer.pipe(
|
||||||
|
@ -45,7 +45,7 @@ export const InspectDataOptions: FC<Props> = ({
|
|||||||
const showFieldConfigsOption = panel && !panel.plugin?.fieldConfigRegistry.isEmpty();
|
const showFieldConfigsOption = panel && !panel.plugin?.fieldConfigRegistry.isEmpty();
|
||||||
|
|
||||||
let dataSelect = dataFrames;
|
let dataSelect = dataFrames;
|
||||||
if (selectedDataFrame === DataTransformerID.seriesToColumns) {
|
if (selectedDataFrame === DataTransformerID.joinByField) {
|
||||||
dataSelect = data!;
|
dataSelect = data!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ export const InspectDataOptions: FC<Props> = ({
|
|||||||
|
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
|
|
||||||
if (selectedDataFrame === DataTransformerID.seriesToColumns) {
|
if (selectedDataFrame === DataTransformerID.joinByField) {
|
||||||
parts.push(t({ id: 'dashboard.inspect-data.series-to-columns', message: 'Series joined by time' }));
|
parts.push(t({ id: 'dashboard.inspect-data.series-to-columns', message: 'Series joined by time' }));
|
||||||
} else if (data.length > 1) {
|
} else if (data.length > 1) {
|
||||||
parts.push(getFrameDisplayName(data[selectedDataFrame as number]));
|
parts.push(getFrameDisplayName(data[selectedDataFrame as number]));
|
||||||
|
@ -44,7 +44,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
/** The string is seriesToColumns transformation. Otherwise it is a dataframe index */
|
/** The string is joinByField transformation. Otherwise it is a dataframe index */
|
||||||
selectedDataFrame: number | DataTransformerID;
|
selectedDataFrame: number | DataTransformerID;
|
||||||
transformId: DataTransformerID;
|
transformId: DataTransformerID;
|
||||||
dataFrameIndex: number;
|
dataFrameIndex: number;
|
||||||
@ -197,7 +197,7 @@ export class InspectDataTab extends PureComponent<Props, State> {
|
|||||||
onDataFrameChange = (item: SelectableValue<DataTransformerID | number>) => {
|
onDataFrameChange = (item: SelectableValue<DataTransformerID | number>) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
transformId:
|
transformId:
|
||||||
item.value === DataTransformerID.seriesToColumns ? DataTransformerID.seriesToColumns : DataTransformerID.noop,
|
item.value === DataTransformerID.joinByField ? DataTransformerID.joinByField : DataTransformerID.noop,
|
||||||
dataFrameIndex: typeof item.value === 'number' ? item.value : 0,
|
dataFrameIndex: typeof item.value === 'number' ? item.value : 0,
|
||||||
selectedDataFrame: item.value!,
|
selectedDataFrame: item.value!,
|
||||||
});
|
});
|
||||||
@ -349,14 +349,14 @@ export class InspectDataTab extends PureComponent<Props, State> {
|
|||||||
function buildTransformationOptions() {
|
function buildTransformationOptions() {
|
||||||
const transformations: Array<SelectableValue<DataTransformerID>> = [
|
const transformations: Array<SelectableValue<DataTransformerID>> = [
|
||||||
{
|
{
|
||||||
value: DataTransformerID.seriesToColumns,
|
value: DataTransformerID.joinByField,
|
||||||
label: t({
|
label: t({
|
||||||
id: 'dashboard.inspect-data.transformation',
|
id: 'dashboard.inspect-data.transformation',
|
||||||
message: 'Series joined by time',
|
message: 'Series joined by time',
|
||||||
}),
|
}),
|
||||||
transformer: {
|
transformer: {
|
||||||
id: DataTransformerID.seriesToColumns,
|
id: DataTransformerID.joinByField,
|
||||||
options: { byField: 'Time' },
|
options: { byField: undefined }, // defaults to time field
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
DataTransformerID,
|
||||||
|
SelectableValue,
|
||||||
|
standardTransformers,
|
||||||
|
TransformerRegistryItem,
|
||||||
|
TransformerUIProps,
|
||||||
|
} from '@grafana/data';
|
||||||
|
import { JoinByFieldOptions, JoinMode } from '@grafana/data/src/transformations/transformers/joinByField';
|
||||||
|
import { Select, InlineFieldRow, InlineField } from '@grafana/ui';
|
||||||
|
|
||||||
|
import { useAllFieldNamesFromDataFrames } from '../utils';
|
||||||
|
|
||||||
|
const modes = [
|
||||||
|
{ value: JoinMode.outer, label: 'OUTER', description: 'Keep all rows from any table with a value' },
|
||||||
|
{ value: JoinMode.inner, label: 'INNER', description: 'Drop rows that do not match a value in all tables' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export function SeriesToFieldsTransformerEditor({ input, options, onChange }: TransformerUIProps<JoinByFieldOptions>) {
|
||||||
|
const fieldNames = useAllFieldNamesFromDataFrames(input).map((item: string) => ({ label: item, value: item }));
|
||||||
|
|
||||||
|
const onSelectField = useCallback(
|
||||||
|
(value: SelectableValue<string>) => {
|
||||||
|
onChange({
|
||||||
|
...options,
|
||||||
|
byField: value?.value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[onChange, options]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSetMode = useCallback(
|
||||||
|
(value: SelectableValue<JoinMode>) => {
|
||||||
|
onChange({
|
||||||
|
...options,
|
||||||
|
mode: value?.value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[onChange, options]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<InlineFieldRow>
|
||||||
|
<InlineField label="Mode" labelWidth={8} grow>
|
||||||
|
<Select options={modes} value={options.mode ?? JoinMode.outer} onChange={onSetMode} />
|
||||||
|
</InlineField>
|
||||||
|
</InlineFieldRow>
|
||||||
|
<InlineFieldRow>
|
||||||
|
<InlineField label="Field" labelWidth={8} grow>
|
||||||
|
<Select
|
||||||
|
options={fieldNames}
|
||||||
|
value={options.byField}
|
||||||
|
onChange={onSelectField}
|
||||||
|
placeholder="time"
|
||||||
|
isClearable
|
||||||
|
/>
|
||||||
|
</InlineField>
|
||||||
|
</InlineFieldRow>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const joinByFieldTransformerRegistryItem: TransformerRegistryItem<JoinByFieldOptions> = {
|
||||||
|
id: DataTransformerID.joinByField,
|
||||||
|
aliasIds: [DataTransformerID.seriesToColumns],
|
||||||
|
editor: SeriesToFieldsTransformerEditor,
|
||||||
|
transformation: standardTransformers.joinByFieldTransformer,
|
||||||
|
name: standardTransformers.joinByFieldTransformer.name,
|
||||||
|
description: standardTransformers.joinByFieldTransformer.description,
|
||||||
|
};
|
@ -1,49 +0,0 @@
|
|||||||
import React, { useCallback } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
DataTransformerID,
|
|
||||||
SelectableValue,
|
|
||||||
standardTransformers,
|
|
||||||
TransformerRegistryItem,
|
|
||||||
TransformerUIProps,
|
|
||||||
} from '@grafana/data';
|
|
||||||
import { SeriesToColumnsOptions } from '@grafana/data/src/transformations/transformers/seriesToColumns';
|
|
||||||
import { Select } from '@grafana/ui';
|
|
||||||
|
|
||||||
import { useAllFieldNamesFromDataFrames } from '../utils';
|
|
||||||
|
|
||||||
export const SeriesToFieldsTransformerEditor: React.FC<TransformerUIProps<SeriesToColumnsOptions>> = ({
|
|
||||||
input,
|
|
||||||
options,
|
|
||||||
onChange,
|
|
||||||
}) => {
|
|
||||||
const fieldNames = useAllFieldNamesFromDataFrames(input).map((item: string) => ({ label: item, value: item }));
|
|
||||||
|
|
||||||
const onSelectField = useCallback(
|
|
||||||
(value: SelectableValue<string>) => {
|
|
||||||
onChange({
|
|
||||||
...options,
|
|
||||||
byField: value?.value,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[onChange, options]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="gf-form-inline">
|
|
||||||
<div className="gf-form gf-form--grow">
|
|
||||||
<div className="gf-form-label width-8">Field name</div>
|
|
||||||
<Select options={fieldNames} value={options.byField} onChange={onSelectField} isClearable />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const seriesToFieldsTransformerRegistryItem: TransformerRegistryItem<SeriesToColumnsOptions> = {
|
|
||||||
id: DataTransformerID.seriesToColumns,
|
|
||||||
editor: SeriesToFieldsTransformerEditor,
|
|
||||||
transformation: standardTransformers.seriesToColumnsTransformer,
|
|
||||||
name: 'Outer join',
|
|
||||||
description:
|
|
||||||
'Joins many time series/tables by a field. This can be used to outer join multiple time series on the _time_ field to show many time series in one table.',
|
|
||||||
};
|
|
@ -11,13 +11,13 @@ import { filterFramesByRefIdTransformRegistryItem } from './editors/FilterByRefI
|
|||||||
import { groupByTransformRegistryItem } from './editors/GroupByTransformerEditor';
|
import { groupByTransformRegistryItem } from './editors/GroupByTransformerEditor';
|
||||||
import { groupingToMatrixTransformRegistryItem } from './editors/GroupingToMatrixTransformerEditor';
|
import { groupingToMatrixTransformRegistryItem } from './editors/GroupingToMatrixTransformerEditor';
|
||||||
import { histogramTransformRegistryItem } from './editors/HistogramTransformerEditor';
|
import { histogramTransformRegistryItem } from './editors/HistogramTransformerEditor';
|
||||||
|
import { joinByFieldTransformerRegistryItem } from './editors/JoinByFieldTransformerEditor';
|
||||||
import { labelsToFieldsTransformerRegistryItem } from './editors/LabelsToFieldsTransformerEditor';
|
import { labelsToFieldsTransformerRegistryItem } from './editors/LabelsToFieldsTransformerEditor';
|
||||||
import { limitTransformRegistryItem } from './editors/LimitTransformerEditor';
|
import { limitTransformRegistryItem } from './editors/LimitTransformerEditor';
|
||||||
import { mergeTransformerRegistryItem } from './editors/MergeTransformerEditor';
|
import { mergeTransformerRegistryItem } from './editors/MergeTransformerEditor';
|
||||||
import { organizeFieldsTransformRegistryItem } from './editors/OrganizeFieldsTransformerEditor';
|
import { organizeFieldsTransformRegistryItem } from './editors/OrganizeFieldsTransformerEditor';
|
||||||
import { reduceTransformRegistryItem } from './editors/ReduceTransformerEditor';
|
import { reduceTransformRegistryItem } from './editors/ReduceTransformerEditor';
|
||||||
import { renameByRegexTransformRegistryItem } from './editors/RenameByRegexTransformer';
|
import { renameByRegexTransformRegistryItem } from './editors/RenameByRegexTransformer';
|
||||||
import { seriesToFieldsTransformerRegistryItem } from './editors/SeriesToFieldsTransformerEditor';
|
|
||||||
import { seriesToRowsTransformerRegistryItem } from './editors/SeriesToRowsTransformerEditor';
|
import { seriesToRowsTransformerRegistryItem } from './editors/SeriesToRowsTransformerEditor';
|
||||||
import { sortByTransformRegistryItem } from './editors/SortByTransformerEditor';
|
import { sortByTransformRegistryItem } from './editors/SortByTransformerEditor';
|
||||||
import { extractFieldsTransformRegistryItem } from './extractFields/ExtractFieldsTransformerEditor';
|
import { extractFieldsTransformRegistryItem } from './extractFields/ExtractFieldsTransformerEditor';
|
||||||
@ -35,7 +35,7 @@ export const getStandardTransformers = (): Array<TransformerRegistryItem<any>> =
|
|||||||
filterFramesByRefIdTransformRegistryItem,
|
filterFramesByRefIdTransformRegistryItem,
|
||||||
filterByValueTransformRegistryItem,
|
filterByValueTransformRegistryItem,
|
||||||
organizeFieldsTransformRegistryItem,
|
organizeFieldsTransformRegistryItem,
|
||||||
seriesToFieldsTransformerRegistryItem,
|
joinByFieldTransformerRegistryItem,
|
||||||
seriesToRowsTransformerRegistryItem,
|
seriesToRowsTransformerRegistryItem,
|
||||||
concatenateTransformRegistryItem,
|
concatenateTransformRegistryItem,
|
||||||
calculateFieldTransformRegistryItem,
|
calculateFieldTransformRegistryItem,
|
||||||
|
Loading…
Reference in New Issue
Block a user