Previous
Filter at the edge
Explore and analyze your captured data using SQL or MQL queries. You can run queries interactively in the Viam app’s query editor or programmatically through the SDK for ad-hoc analysis, building dashboards, or integrating with your own tools.
Tabular data (sensor readings, motor positions, encoder ticks, and other structured key-value data) is queryable through SQL and MQL. Binary data (images, point clouds) is stored separately and accessible through the data client API.
SQL is good for straightforward filtering, sorting, and limiting. MQL (MongoDB Query Language) uses aggregation pipelines and is more powerful for grouping, computing averages, and restructuring nested data.
By default, queries run against the readings collection in the sensorData database.
See Query reference for the full schema.
Start with a broad query to see what data you have:
SELECT time_received, component_name, component_type, data
FROM readings
ORDER BY time_received DESC
LIMIT 10
This shows the 10 most recent readings across all components.
Most of the interesting values are in the data column, which contains your actual readings as nested JSON.
To see the structure of your data, run this query for a specific component:
SELECT data FROM readings WHERE component_name = 'my-sensor' LIMIT 1
Switch to table view (the table icon in the results area) to see nested fields automatically flattened into dot-notation column headers like data.readings.temperature. These dot-notation paths are exactly what you use in your queries to extract specific values.
For the full schema and per-component examples, see the readings table schema.
To narrow to a specific component:
SELECT time_received, data
FROM readings
WHERE component_name = 'my-sensor'
ORDER BY time_received DESC
LIMIT 10
To filter by time range:
SELECT time_received, component_name, data
FROM readings
WHERE time_received > '2025-01-15T00:00:00Z'
AND time_received < '2025-01-16T00:00:00Z'
ORDER BY time_received ASC
The data column contains JSON, so you need JSON functions to extract specific
values. Use dot notation to reach into the nested structure:
SELECT
time_received,
data.readings.temperature AS temperature,
data.readings.humidity AS humidity
FROM readings
WHERE component_name = 'my-sensor'
ORDER BY time_received DESC
LIMIT 20
For detection results from a vision service:
SELECT
time_received,
data.detections
FROM readings
WHERE component_name = 'my-detector'
AND component_type = 'rdk:service:vision'
ORDER BY time_received DESC
LIMIT 10
To filter by a specific machine:
SELECT time_received, component_name, data
FROM readings
WHERE robot_id = 'YOUR-MACHINE-ID'
ORDER BY time_received DESC
LIMIT 10
Switch to MQL mode in the query editor. MQL queries are JSON arrays where each element is a pipeline stage.
Get the last 10 readings from a component:
[
{ "$match": { "component_name": "my-sensor" } },
{ "$sort": { "time_received": -1 } },
{ "$limit": 10 },
{
"$project": {
"time_received": 1,
"data": 1,
"_id": 0
}
}
]
Count readings per component:
[
{
"$group": {
"_id": "$component_name",
"count": { "$sum": 1 }
}
},
{ "$sort": { "count": -1 } }
]
Count readings per component over a specific time window:
[
{
"$match": {
"time_received": {
"$gte": { "$date": "2025-01-15T00:00:00Z" },
"$lt": { "$date": "2025-01-16T00:00:00Z" }
}
}
},
{
"$group": {
"_id": "$component_name",
"count": { "$sum": 1 }
}
},
{ "$sort": { "count": -1 } }
]
Compute average, min, and max of a sensor value:
[
{ "$match": { "component_name": "my-sensor" } },
{
"$group": {
"_id": null,
"avg_temperature": { "$avg": "$data.readings.temperature" },
"min_temperature": { "$min": "$data.readings.temperature" },
"max_temperature": { "$max": "$data.readings.temperature" },
"total_readings": { "$sum": 1 }
}
}
]
Group readings by hour to see trends over time:
[
{ "$match": { "component_name": "my-sensor" } },
{
"$group": {
"_id": {
"$dateToString": {
"format": "%Y-%m-%d %H:00",
"date": "$time_received"
}
},
"avg_temperature": { "$avg": "$data.readings.temperature" },
"count": { "$sum": 1 }
}
},
{ "$sort": { "_id": 1 } }
]
Find all detections above a confidence threshold:
[
{ "$match": { "component_name": "my-detector" } },
{ "$unwind": "$data.detections" },
{ "$match": { "data.detections.confidence": { "$gte": 0.9 } } },
{
"$project": {
"time_received": 1,
"class_name": "$data.detections.class_name",
"confidence": "$data.detections.confidence",
"_id": 0
}
},
{ "$sort": { "time_received": -1 } },
{ "$limit": 20 }
]
The $unwind stage is important when your data contains arrays. It flattens
the array so each element becomes its own document, which you can then filter
and project individually.
You can run the same SQL and MQL queries from Python or Go using the data client API. See Query data from code for setup instructions and examples.
To get oriented with your own data:
SELECT DISTINCT component_name FROM readings to see what components have captured data.SELECT data FROM readings WHERE component_name = 'YOUR-COMPONENT' LIMIT 1 to see the JSON structure of its readings.data.readings.temperature).For the full schema of the readings table, see Query reference.
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!