Skip to content

Query Command

The query command executes and retrieves the results of a query on a specified connection and returns the results in table format, JSON, or CSV.

You can run it in three modes:

  • Direct query: provide --connection and --query
  • Asset query: provide --asset (optional --environment) to execute the SQL from an asset file
  • Auto-detect: provide --asset + --query to run an ad-hoc query using the asset's connection and dialect
  • Semantic query: provide --semantic-model with --asset or --pipeline to query a semantic model

Flags:

FlagAliasDescription
--connection-cThe name of the connection to use (direct query mode).
--query-qThe SQL query to execute.
--assetPath to a SQL asset file within a Bruin pipeline.
--pipelinePath to a Bruin pipeline. Used with --semantic-model when no asset is provided.
--environment--envTarget environment name as defined in .bruin.yml.
--semantic-modelSemantic model name to compile and query.
--metricSemantic metric to select. Can be passed multiple times.
--dimensionSemantic dimension to select. Use name:granularity for time dimensions. Can be passed multiple times.
--filterSemantic filter as JSON, for example {"dimension":"country","operator":"equals","value":"US"}. Can be passed multiple times.
--segmentSemantic segment to apply. Can be passed multiple times.
--sortSemantic sort field. Use name:asc or name:desc. Can be passed multiple times.
--varSet a Jinja template variable for query rendering. Supports flat, dot-notation nested, and JSON values. Can be passed multiple times. See Template variables.
--start-dateStart date for query variables in YYYY-MM-DD or YYYY-MM-DD HH:MM:SS.
--end-dateEnd date for query variables in YYYY-MM-DD or YYYY-MM-DD HH:MM:SS.
--limit-lLimit the number of rows returned.
--timeout-tTimeout for query execution in seconds (default: 1000).
--output [format]-oOutput type: plain, json, csv.
--exportExport results to a CSV file.
--split-rowsSplit export into multiple CSV files with at most this many rows per file (requires --export).
--config-fileThe path to the .bruin.yml file.
--dangerously-bypass-soft-limitsBypass BigQuery soft query limits configured on the connection.

Example

bash
bruin query --connection my_connection --query "SELECT * FROM table"

Example output:

plaintext
+-------------+-------------+----------------+
|   Column1   |   Column2   |    Column3     |
+-------------+-------------+----------------+
| Value1      | Value2      | Value3         |
| Value4      | Value5      | Value6         |
| Value7      | Value8      | Value9         |
+-------------+-------------+----------------+

Splitting Large Exports

When exporting large query results, you can use --split-rows to split the output into multiple CSV files. This is useful when:

  • Your query returns millions of rows that are too large for a single file
  • You need to process the data in chunks
  • You're working with tools that have file size limitations

Example:

bash
# Export a large table, splitting into files of 400,000 rows each
bruin query --connection my_connection --query "SELECT * FROM large_table" --export --split-rows 400000

If your query returns 1,000,000 rows with --split-rows 400000, you'll get 3 files:

  • query_result_<timestamp>_part1.csv (400,000 rows)
  • query_result_<timestamp>_part2.csv (400,000 rows)
  • query_result_<timestamp>_part3.csv (200,000 rows)

Each file includes the header row with column names.

Template variables

You can inject Jinja template variables into a query with --var. The flag can be passed multiple times and supports flat, nested, and JSON values, so you can test dashboard-style SQL — including nested filters.* variables — directly from the CLI.

Flat variables:

bash
bruin query --connection my_connection \
  --query "SELECT * FROM events WHERE date >= '{{ start_date }}'" \
  --var start_date=2026-05-20

Nested variables (dot-notation):

Use a dotted key to build a nested object. This matches the nested filters object the dashboard runtime injects, so {{ filters.start_date }} resolves as expected:

bash
bruin query --connection my_connection \
  --query "SELECT * FROM events WHERE date >= '{{ filters.start_date }}'" \
  --var filters.start_date=2026-05-20 \
  --var filters.end_date=2026-05-27

Nested variables (JSON):

You can also pass a whole object (or array) as a JSON value:

bash
bruin query --connection my_connection \
  --query "SELECT * FROM events WHERE date >= '{{ filters.start_date }}'" \
  --var filters='{"start_date":"2026-05-20","end_date":"2026-05-27"}'

Scalar values are kept as literal strings (matching how pipeline variables work in YAML); only values that look like a JSON object or array are parsed as JSON.

Querying MongoDB

MongoDB connections (mongo and mongo_atlas) are not SQL, so the --query value is a JSON object describing a single find or aggregation against one collection instead of a SQL statement. The returned documents are flattened into a table: columns are the union of the top-level fields (in first-seen order), and nested documents and arrays are shown as JSON.

The envelope fields are:

FieldDescription
collectionRequired. The collection to query.
filterFind filter document. Defaults to {} (all documents).
projectionFind projection, e.g. {"name":1,"_id":0}.
sortFind sort, e.g. {"age":-1}.
limitMaximum number of documents to return.
skipNumber of documents to skip.
aggregateAggregation pipeline (an array of stages). Mutually exclusive with filter/projection/sort.
databaseOverride the connection's configured database for this query.

Values are parsed as MongoDB Extended JSON, so query operators such as $gt, $and, and $match pass through unchanged while type wrappers such as {"$oid":"..."} and {"$date":"..."} are interpreted as the corresponding BSON types.

NOTE

The SQL-oriented --limit flag does not apply to MongoDB queries. Set "limit" inside the envelope instead.

Find example:

bash
bruin query --connection my_mongo \
  --query '{"collection":"users","filter":{"age":{"$gt":21}},"sort":{"age":-1},"limit":10}'
plaintext
+--------------------------+-------+-----+-----------+----------------+
|           _id            | name  | age |   tags    |    address     |
+--------------------------+-------+-----+-----------+----------------+
| 6a3bb9d9ca6a1b41199df8a5 | carol | 41  | ["x"]     |                |
| 6a3bb9d9ca6a1b41199df8a3 | alice | 30  | ["a","b"] | {"city":"NYC"} |
+--------------------------+-------+-----+-----------+----------------+

Aggregation example:

bash
bruin query --connection my_mongo \
  --query '{"collection":"orders","aggregate":[{"$group":{"_id":"$status","n":{"$sum":1}}}]}'

Semantic Queries

Semantic query mode compiles metrics, dimensions, segments, filters, joins, and windows from YAML models in the repository-level semantic directory. See the semantic layer documentation for model syntax.

Use an asset path when you want Bruin to infer the pipeline, connection, and SQL dialect from an existing SQL asset:

bash
bruin query \
  --asset ./pipelines/daily-orders/assets/orders.sql \
  --semantic-model orders \
  --dimension order_date:month \
  --metric revenue \
  --metric avg_order_value \
  --filter '{"dimension":"country","operator":"equals","value":"US"}' \
  --segment completed \
  --sort order_date:asc \
  --output json

Use a pipeline path when there is no anchor asset. In this mode, pass the connection explicitly:

bash
bruin query \
  --pipeline ./pipelines/daily-orders \
  --connection warehouse \
  --semantic-model orders \
  --dimension customers.country \
  --metric revenue \
  --sort revenue:desc \
  --output csv

Semantic query mode cannot be combined with --query.