This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git
The following commit(s) were added to refs/heads/main by this push:
new 548cdd73 Add BDSL documentation for BanyanDB Query Language (#737)
548cdd73 is described below
commit 548cdd738485a8f1629d6ceb77daf09ebf0106b3
Author: Gao Hongtao <[email protected]>
AuthorDate: Thu Aug 28 00:21:11 2025 +0800
Add BDSL documentation for BanyanDB Query Language (#737)
---
.gitignore | 1 +
docs/interacting/bydbql.md | 568 +++++++++++++++++++++++++++++++++++++++++++++
docs/menu.yml | 2 +
3 files changed, 571 insertions(+)
diff --git a/.gitignore b/.gitignore
index 474f67fe..75dae5b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,4 +72,5 @@ gomock_reflect*
# Claude
Claude.md
.claude/
+CLAUDE.md
diff --git a/docs/interacting/bydbql.md b/docs/interacting/bydbql.md
new file mode 100644
index 00000000..9415ff72
--- /dev/null
+++ b/docs/interacting/bydbql.md
@@ -0,0 +1,568 @@
+# BanyanDB Query Language (BydbQL)
+
+## 1. Introduction
+
+### 1.1. Purpose
+
+This document outlines the design of the BanyanDB Data Query Language
(BydbQL), a unified query language with SQL-like syntax for all of BanyanDB's
data models. The primary goal of BydbQL is to provide users with a familiar,
intuitive, and powerful interface to interact with their data, abstracting the
underlying protobuf-based APIs for streams, measures, properties, and Top-N
queries.
+
+This document specifies the language's syntax, its semantics, and the precise
mapping from BydbQL statements to the various `Request` messages.
+
+### 1.2. Scope
+
+BydbQL supports querying across BanyanDB's primary data models:
+* **Streams**: For raw, time-series elements like logs and traces.
+* **Measures**: For aggregated numerical time-series data (metrics).
+* **Properties**: For metadata and key-value information.
+
+It also provides a specialized syntax for optimized **Top-N** queries against
measures.
+
+## 2. Core Concepts
+
+### 2.1. Parser Architecture
+
+BydbQL queries will be processed by a classic three-stage compiler front-end
architecture, which ensures modularity and maintainability.
+
+```
+BydbQL Query String
+ ↓
+ Lexer
+ ↓
+ Parser
+ ↓
+Abstract Syntax Tree (AST)
+ ↓
+ Transformer
+ ↓
+ Protobuf Request
+```
+* **Lexer**: Breaks the query string into a sequence of tokens.
+* **Parser**: Builds an Abstract Syntax Tree (AST) from the tokens,
validating the query's syntax.
+* **Transformer**: Traverses the AST, performs semantic analysis using a
schema, and transforms the AST into the appropriate target protobuf `Request`
message.
+
+### 2.2. Distinguishing Query Types
+
+BydbQL distinguishes the target data model either explicitly through keywords
in the `FROM` clause or implicitly through the **execution context**. This
allows the parser to apply the correct grammar and transformation rules for the
query.
+
+* **Explicit**: `FROM STREAM <name>`, `FROM MEASURE <name>`, `FROM PROPERTY
<name>`
+* **Implicit**: The query is executed against a resource-specific endpoint
(e.g., `/v1/streams/{stream_name}/query`), where the type and name of the
resource are known.
+
+Specialized queries, like Top-N, use a distinct top-level command and
typically require an explicit `FROM` clause:
+
+* **Top-N**: `SHOW TOPN ... FROM MEASURE <measure_name>`
+
+### 2.3. Optional `FROM` Clause
+
+In BydbQL, the `FROM` clause is **optional** for `SELECT` queries. When it is
omitted, the target resource (the specific stream, measure, or property)
**must** be supplied by the execution context.
+
+The simplest possible BydbQL query is `SELECT *`. When executed within the
context of a stream named `sw`, this is equivalent to `SELECT * FROM STREAM sw`.
+
+When the `FROM` clause is present, it overrides any context provided by the
environment. This is useful for clients that connect to a generic query
endpoint and need to specify the target resource directly within the query text.
+
+### 2.4. Case Sensitivity
+
+BydbQL follows SQL-like conventions for case sensitivity:
+
+* **Reserved words are case-insensitive**: Keywords like `SELECT`, `FROM`,
`WHERE`, `ORDER BY`, `TIME`, `BETWEEN`, `AND`, etc. can be written in any case
combination.
+* **Identifiers are case-sensitive**: Names of streams, measures,
properties, tags, and fields preserve their case and must be referenced exactly
as defined.
+
+#### Examples
+
+All of these queries are equivalent:
+```sql
+SELECT * FROM STREAM sw WHERE service_id = 'webapp';
+
+select * from stream sw where service_id = 'webapp';
+
+Select * From Stream sw Where service_id = 'webapp';
+```
+
+But these refer to different identifiers:
+```sql
+-- Different tag names (case-sensitive)
+SELECT ServiceName FROM STREAM sw; -- refers to tag "ServiceName"
+SELECT servicename FROM STREAM sw; -- refers to tag "servicename"
+
+-- Different stream names (case-sensitive)
+FROM STREAM MyStream -- refers to stream "MyStream"
+FROM STREAM mystream -- refers to stream "mystream"
+```
+
+**Best Practice**: Use uppercase for reserved words and consistent casing for
identifiers to maintain readability.
+
+## 2.5. Timestamp Formats
+
+BydbQL supports flexible timestamp specifications in TIME clauses,
accommodating both absolute and relative time formats:
+
+### 2.5.1. Absolute Time Format
+
+Absolute timestamps use the RFC3339 standard format:
+```
+"2006-01-02T15:04:05Z07:00"
+```
+
+Examples:
+* `"2023-01-01T00:00:00Z"` - January 1, 2023, 00:00:00 UTC
+* `"2023-01-01T15:30:45+08:00"` - January 1, 2023, 15:30:45 UTC+8
+* `"2023-12-31T23:59:59Z"` - December 31, 2023, 23:59:59 UTC
+
+### 2.5.2. Relative Time Format
+
+Relative timestamps are duration strings that are evaluated relative to the
current time:
+```
+[-][duration]
+```
+
+Supported duration units:
+* `m` - minutes
+* `h` - hours
+* `d` - days
+* `w` - weeks
+
+Examples:
+* `"-30m"` - 30 minutes ago
+* `"2h"` - 2 hours from now
+* `"-1d"` - 1 day ago
+* `"-1w"` - 1 week ago
+* `"now"` - current time
+
+### 2.5.3. Usage in TIME Clauses
+
+Both absolute and relative formats can be used interchangeably in TIME
conditions:
+
+```sql
+-- Absolute time examples
+TIME = '2023-01-01T00:00:00Z'
+TIME BETWEEN '2023-01-01T00:00:00Z' AND '2023-01-02T00:00:00Z'
+TIME > '2023-01-01T08:00:00Z'
+
+-- Relative time examples
+TIME > '-30m'
+TIME BETWEEN '-1h' AND 'now'
+TIME < '-1d'
+```
+
+The `parseTime` function automatically determines whether a timestamp is
absolute (RFC3339) or relative (duration string) and converts it appropriately.
+
+## 4. BydbQL for Streams
+
+BydbQL for streams is designed for querying and retrieving raw time-series
elements. The syntax maps to the `banyandb.stream.v1.QueryRequest` message.
+
+### 4.1. Grammar
+
+```
+query ::= SELECT projection [from_stream_clause] [TIME
time_condition] [WHERE criteria] [ORDER BY order_expression] [LIMIT integer]
[OFFSET integer]
+from_stream_clause ::= "FROM STREAM" identifier ["IN" "(" group_list ")"]
+projection ::= "*" | column_list
+column_list ::= identifier ("," identifier)*
+group_list ::= identifier ("," identifier)*
+criteria ::= condition (("AND" | "OR") condition)*
+condition ::= identifier binary_op (value | value_list)
+time_condition ::= "=" timestamp | ">" timestamp | "<" timestamp | ">="
timestamp | "<=" timestamp | "BETWEEN" timestamp "AND" timestamp
+binary_op ::= "=" | "!=" | ">" | "<" | ">=" | "<=" | "IN" | "NOT IN" |
"HAVING" | "NOT HAVING" | "MATCH"
+order_expression::= identifier ["ASC" | "DESC"]
+value ::= string_literal | integer_literal | "NULL"
+value_list ::= "(" value ("," value)* ")"
+timestamp ::= string_literal | integer_literal
+ /* timestamp supports both absolute and relative time formats:
+ - Absolute: RFC3339 format like "2006-01-02T15:04:05Z07:00"
+ - Relative: duration strings like "-30m", "2h", "1d" (relative to
current time) */
+identifier ::= [a-zA-Z_][a-zA-Z0-9_]*
+string_literal ::= "'" [^']* "'" | "\"" [^\"]* "\""
+integer_literal ::= [0-9]+
+```
+
+### 4.2. Mapping to `stream.v1.QueryRequest`
+
+* **`FROM STREAM name IN (groups)`**: Maps to the `name` and `groups`
fields. If the clause is omitted, these values are taken from the execution
context.
+* **`SELECT tags`**: Maps to `projection`. Requires a stream schema to
resolve tags to their families.
+* **`TIME = '2023-01-01T00:00:00Z'`**: Maps to `time_range` with `begin` and
`end` set to the same timestamp.
+* **`TIME > '2023-01-01T00:00:00Z'`**: Maps to `time_range` with `begin` set
to the timestamp.
+* **`TIME BETWEEN '2023-01-01T00:00:00Z' AND '2023-01-02T00:00:00Z'`**: Maps
to `time_range` with `begin` and `end` set to the respective timestamps.
+* **`TIME > '-30m'`**: Maps to `time_range` with `begin` set to 30 minutes
ago.
+* **`TIME BETWEEN '-1h' AND 'now'`**: Maps to `time_range` from 1 hour ago
to current time.
+* **`WHERE conditions`**: Maps to `criteria`.
+* **`ORDER BY field`**: Maps to `order_by`.
+* **`LIMIT`/`OFFSET`**: Maps to `limit` and `offset`.
+
+### 4.3. Examples
+
+```sql
+-- Simplest query (context must provide the stream name, e.g., 'sw')
+SELECT *;
+
+-- Basic selection with filtering and ordering
+SELECT trace_id, service_id
+FROM STREAM sw IN (default, updated)
+WHERE service_id = 'webapp' AND state = 1
+ORDER BY start_time DESC
+LIMIT 100;
+
+-- Project all tags from a stream (FROM is explicit)
+SELECT *
+FROM STREAM sw
+WHERE state = 0
+LIMIT 10;
+
+-- Use more complex conditions with IN and OR
+SELECT trace_id, duration
+WHERE service_id IN ('webapp', 'api-gateway') OR http.method = 'POST';
+
+-- Query with time range using TIME clause
+SELECT trace_id, service_id, start_time
+FROM STREAM sw
+TIME BETWEEN '2023-01-01T00:00:00Z' AND '2023-01-02T00:00:00Z'
+WHERE service_id = 'webapp'
+ORDER BY start_time DESC;
+
+-- Query data after a specific timestamp
+SELECT *
+FROM STREAM sw
+TIME > '2023-01-01T12:00:00Z'
+WHERE state = 1
+LIMIT 100;
+
+-- Query data at an exact timestamp
+SELECT trace_id, duration
+FROM STREAM sw
+TIME = '2023-01-01T15:30:00Z';
+
+-- Query with relative time - last 30 minutes
+SELECT *
+FROM STREAM sw
+TIME > '-30m'
+WHERE state = 1
+LIMIT 100;
+
+-- Query with relative time range - last 2 hours
+SELECT trace_id, service_id, start_time
+FROM STREAM sw
+TIME BETWEEN '-2h' AND 'now'
+WHERE service_id = 'webapp'
+ORDER BY start_time DESC;
+
+-- Query data within the last hour using absolute time
+SELECT *
+FROM STREAM sw
+TIME >= '2023-01-01T13:00:00Z'
+WHERE status = 'error';
+
+-- Query data older than 1 day ago
+SELECT trace_id, duration
+FROM STREAM sw
+TIME < '-1d';
+```
+
+## 5. BydbQL for Measures
+
+BydbQL for measures is tailored for analytical queries on aggregated numerical
data. It supports aggregation, grouping, and mixed selection of tags and
fields, mapping to the `banyandb.measure.v1.QueryRequest` message.
+
+### 5.1. Grammar
+
+```
+measure_query ::= SELECT projection [from_measure_clause] [TIME
time_condition] [WHERE criteria] [GROUP BY group_list] [ORDER BY
order_expression] [LIMIT integer] [OFFSET integer]
+from_measure_clause ::= "FROM MEASURE" identifier ["IN" "(" group_list ")"]
+projection ::= "*" | (column_list | agg_function "(" identifier ")" |
"TOP" integer projection)
+column_list ::= identifier ("," identifier)* ["::tag" | "::field"]
+agg_function ::= "SUM" | "MEAN" | "COUNT" | "MAX" | "MIN"
+group_list ::= identifier ("," identifier)*
+criteria ::= condition (("AND" | "OR") condition)*
+condition ::= identifier binary_op (value | value_list)
+time_condition ::= "=" timestamp | ">" timestamp | "<" timestamp | ">="
timestamp | "<=" timestamp | "BETWEEN" timestamp "AND" timestamp
+binary_op ::= "=" | "!=" | ">" | "<" | ">=" | "<=" | "IN" | "NOT IN" |
"HAVING" | "NOT HAVING" | "MATCH"
+order_expression ::= identifier ["ASC" | "DESC"]
+value ::= string_literal | integer_literal | "NULL"
+value_list ::= "(" value ("," value)* ")"
+timestamp ::= string_literal | integer_literal
+ /* timestamp supports both absolute and relative time formats:
+ - Absolute: RFC3339 format like "2006-01-02T15:04:05Z07:00"
+ - Relative: duration strings like "-30m", "2h", "1d" (relative to
current time) */
+identifier ::= [a-zA-Z_][a-zA-Z0-9_]*
+string_literal ::= "'" [^']* "'" | "\"" [^\"]* "\""
+integer_literal ::= [0-9]+
+```
+
+### 5.2. BydbQL Extensions for `SELECT`
+
+The `SELECT` clause for measures is highly flexible, allowing for the
selection of tags, fields, and aggregations in a single, flat list.
+
+* `SELECT <field_key>, <tag_key>`: Returns specific fields and tags. The
parser will infer the type of each identifier from the measure's schema.
+* `SELECT <identifier>::field, <identifier>::tag`: If a field and a tag
share the same name, the `::field` or `::tag` syntax **must** be used to
disambiguate the identifier's type.
+* The clause also supports aggregation functions (`SUM`, `MEAN`, `COUNT`,
`MAX`, `MIN`) and a `TOP N` clause for ranked results.
+
+### 5.3. Mapping to `measure.v1.QueryRequest`
+
+* **`FROM MEASURE name IN (groups)`**: Maps to the `name` and `groups`
fields. If the clause is omitted, these values are taken from the execution
context.
+* **`SELECT <tag1>, <field1>, <field2>`**: The transformer inspects each
identifier. Those identified as tags (either by schema lookup or `::tag`) are
added to `tag_projection`. Those identified as fields (by schema lookup or
`::field`) are added to `field_projection`.
+* **`SELECT SUM(field)`**: Maps to `agg`.
+* **`TIME = '2023-01-01T00:00:00Z'`**: Maps to `time_range` with `begin` and
`end` set to the same timestamp.
+* **`TIME > '2023-01-01T00:00:00Z'`**: Maps to `time_range` with `begin` set
to the timestamp.
+* **`TIME BETWEEN '2023-01-01T00:00:00Z' AND '2023-01-02T00:00:00Z'`**: Maps
to `time_range` with `begin` and `end` set to the respective timestamps.
+* **`TIME > '-30m'`**: Maps to `time_range` with `begin` set to 30 minutes
ago.
+* **`TIME BETWEEN '-1h' AND 'now'`**: Maps to `time_range` from 1 hour ago
to current time.
+* **`GROUP BY <tag1>, <tag2>`**: The `GROUP BY` clause takes a simple list
of tags and maps to `group_by.tag_projection`.
+* **`SELECT TOP N ...`**: Maps to the `top` message.
+
+### 5.4. Examples
+
+```sql
+-- Simplest query (context must provide measure name)
+SELECT *;
+
+-- Select a specific tag and a specific field
+SELECT
+ instance,
+ latency
+WHERE region = 'us-west-1'
+LIMIT 10;
+
+-- Select multiple tags and fields, with an aggregation
+SELECT
+ region,
+ SUM(latency)
+FROM MEASURE service_cpm
+GROUP BY region;
+
+-- Disambiguate a key named 'status' that exists as both a tag and a field
+SELECT
+ status::tag,
+ status::field
+FROM MEASURE http_requests
+WHERE path = '/api/v1/users';
+
+-- Find the top 10 instances with the highest CPU usage for a specific service
+SELECT TOP 10
+ instance,
+ cpu_usage
+FROM MEASURE instance_metrics
+WHERE service = 'auth-service'
+ORDER BY cpu_usage DESC;
+
+-- Select aggregated latency from multiple groups
+SELECT
+ region,
+ SUM(latency)
+FROM MEASURE service_cpm IN (us-west, us-east, eu-central)
+GROUP BY region;
+
+-- Query measures with time range using TIME clause
+SELECT
+ service,
+ AVG(response_time)
+FROM MEASURE http_metrics
+TIME BETWEEN '2023-01-01T00:00:00Z' AND '2023-01-02T00:00:00Z'
+WHERE region = 'us-west'
+GROUP BY service;
+
+-- Query measures after a specific time
+SELECT
+ instance,
+ MAX(cpu_usage)
+FROM MEASURE system_metrics
+TIME > '2023-01-01T08:00:00Z'
+WHERE datacenter = 'dc-1'
+GROUP BY instance
+ORDER BY MAX(cpu_usage) DESC;
+
+-- Query measures at exact timestamp
+SELECT
+ endpoint,
+ SUM(request_count)
+FROM MEASURE api_metrics
+TIME = '2023-01-01T10:00:00Z'
+WHERE method = 'POST'
+GROUP BY endpoint;
+
+-- Query measures with relative time - last 30 minutes
+SELECT
+ service,
+ AVG(response_time)
+FROM MEASURE http_metrics
+TIME > '-30m'
+WHERE region = 'us-west'
+GROUP BY service;
+
+-- Query measures with relative time range - last 2 hours
+SELECT
+ instance,
+ MAX(cpu_usage)
+FROM MEASURE system_metrics
+TIME BETWEEN '-2h' AND 'now'
+WHERE datacenter = 'dc-1'
+GROUP BY instance
+ORDER BY MAX(cpu_usage) DESC;
+
+-- Query data older than 1 day ago
+SELECT
+ endpoint,
+ SUM(error_count)
+FROM MEASURE api_errors
+TIME < '-1d'
+WHERE status_code = '500'
+GROUP BY endpoint;
+```
+
+## 6. BydbQL for Top-N
+
+Top-N queries use a specialized, command-like syntax for clarity and to
reflect the optimized nature of the underlying
`banyandb.measure.v1.TopNRequest`. The `FROM` clause is mandatory.
+
+### 6.1. Grammar
+
+```
+topn_query ::= SHOW TOP integer from_measure_clause [TIME
time_condition] [WHERE topn_criteria] [AGGREGATE BY agg_function] [ORDER BY
value ["ASC"|"DESC"]]
+from_measure_clause ::= "FROM MEASURE" identifier ["IN" "(" group_list ")"]
+topn_criteria ::= condition (("AND" | "OR") condition)*
+condition ::= identifier binary_op (value | value_list)
+time_condition ::= "=" timestamp | ">" timestamp | "<" timestamp | ">="
timestamp | "<=" timestamp | "BETWEEN" timestamp "AND" timestamp
+binary_op ::= "=" | "!=" | ">" | "<" | ">=" | "<=" | "IN" | "NOT IN"
+agg_function ::= "SUM" | "MEAN" | "COUNT" | "MAX" | "MIN"
+group_list ::= identifier ("," identifier)*
+value ::= string_literal | integer_literal | "NULL"
+value_list ::= "(" value ("," value)* ")"
+timestamp ::= string_literal | integer_literal
+ /* timestamp supports both absolute and relative time formats:
+ - Absolute: RFC3339 format like "2006-01-02T15:04:05Z07:00"
+ - Relative: duration strings like "-30m", "2h", "1d" (relative to
current time) */
+identifier ::= [a-zA-Z_][a-zA-Z0-9_]*
+string_literal ::= "'" [^']* "'" | "\"" [^\"]* "\""
+integer_literal ::= [0-9]+
+```
+
+### 6.2. Mapping to `measure.v1.TopNRequest`
+
+* **`SHOW TOP N`**: Maps to `top_n`.
+* **`FROM MEASURE name IN (groups)`**: Maps to the `name` and `groups`
fields.
+* **`TIME BETWEEN '2023-01-01T00:00:00Z' AND '2023-01-02T00:00:00Z'`**: Maps
to `time_range` with `begin` and `end` set to the respective timestamps.
+* **`TIME > '-30m'`**: Maps to `time_range` with `begin` set to 30 minutes
ago.
+* **`TIME BETWEEN '-1h' AND 'now'`**: Maps to `time_range` from 1 hour ago
to current time.
+* **`WHERE tag = 'value'`**: Maps to `conditions`. Only simple equality is
supported.
+* **`AGGREGATE BY FUNC`**: Maps to `agg`.
+* **`ORDER BY value DESC`**: Maps to `field_value_sort`.
+
+### 6.3. Examples
+
+```sql
+-- Get the Top 10 services with the highest latency
+SHOW TOP 10
+FROM MEASURE service_latency
+WHERE http_method = 'GET' AND version = 'v1.2.0'
+ORDER BY value DESC;
+
+-- Get the Bottom 5 services with the fewest errors
+SHOW TOP 5
+FROM MEASURE service_errors_total
+ORDER BY value ASC;
+
+-- Get the Top 3 pods with the most restarts in total over the time range
+SHOW TOP 3
+FROM MEASURE pod_restarts
+WHERE namespace = 'production'
+AGGREGATE BY SUM;
+
+-- Get the Top 5 services with the highest error rate across multiple groups
+SHOW TOP 5
+FROM MEASURE service_errors IN (production, staging)
+ORDER BY value DESC;
+
+-- Get the Top 10 services with highest latency in the last hour
+SHOW TOP 10
+FROM MEASURE service_latency
+TIME > '2023-01-01T13:00:00Z'
+ORDER BY value DESC;
+
+-- Get the Top 5 endpoints with most errors in a specific time range
+SHOW TOP 5
+FROM MEASURE endpoint_errors
+TIME BETWEEN '2023-01-01T00:00:00Z' AND '2023-01-02T00:00:00Z'
+WHERE status_code = '500'
+ORDER BY value DESC;
+
+-- Get the Top 10 services with highest latency in the last hour
+SHOW TOP 10
+FROM MEASURE service_latency
+TIME > '-1h'
+ORDER BY value DESC;
+
+-- Get the Top 5 endpoints with most errors in the last 24 hours
+SHOW TOP 5
+FROM MEASURE endpoint_errors
+TIME BETWEEN '-24h' AND 'now'
+WHERE status_code = '500'
+ORDER BY value DESC;
+
+-- Get the Top 3 services with lowest response time in the last 30 minutes
+SHOW TOP 3
+FROM MEASURE service_response_time
+TIME > '-30m'
+ORDER BY value ASC;
+```
+
+## 7. BydbQL for Properties
+
+BydbQL for properties is designed for simple key-value lookups and metadata
filtering. It maps to the `banyandb.property.v1.QueryRequest` message.
+
+### 7.1. Grammar
+
+```
+property_query ::= SELECT projection [from_property_clause] [WHERE
criteria] [LIMIT integer]
+from_property_clause ::= "FROM PROPERTY" identifier ["IN" "(" group_list ")"]
+projection ::= "*" | column_list
+column_list ::= identifier ("," identifier)*
+group_list ::= identifier ("," identifier)*
+criteria ::= condition (("AND" | "OR") condition)*
+condition ::= identifier binary_op (value | value_list) | "ID"
binary_op (value | value_list)
+binary_op ::= "=" | "!=" | ">" | "<" | ">=" | "<=" | "IN" | "NOT IN"
+value ::= string_literal | integer_literal | "NULL"
+value_list ::= "(" value ("," value)* ")"
+identifier ::= [a-zA-Z_][a-zA-Z0-9_]*
+string_literal ::= "'" [^']* "'" | "\"" [^\"]* "\""
+integer_literal ::= [0-9]+
+```
+
+### 7.2. Mapping to `property.v1.QueryRequest`
+
+* **`FROM PROPERTY name IN (groups)`**: Maps to the `name` and `groups`
fields. If the clause is omitted, these values are taken from the execution
context.
+* **`SELECT tags`**: Maps to `tag_projection`.
+* **`WHERE ID IN (...)`**: Maps to `ids`.
+* **`WHERE tag = 'value'`**: Maps to `criteria`.
+* **`LIMIT n`**: Maps to `limit`.
+
+### 7.3. Examples
+
+```sql
+-- Simplest query (context must provide property name)
+SELECT *;
+
+-- Find properties by filtering on their tags
+SELECT ip, owner
+FROM PROPERTY server_metadata
+WHERE datacenter = 'dc-101' AND in_service = 'true'
+LIMIT 50;
+
+-- Retrieve a specific property by its unique ID
+SELECT *
+WHERE ID = 'server-1a2b3c';
+
+-- Retrieve a set of properties by their unique IDs
+SELECT ip, region
+FROM PROPERTY server_metadata
+WHERE ID IN ('server-1a2b3c', 'server-4d5e6f');
+
+-- Find properties from multiple groups
+SELECT ip, owner
+FROM PROPERTY server_metadata IN (datacenter-1, datacenter-2, datacenter-3)
+WHERE in_service = 'true'
+LIMIT 100;
+```
+
+## 8. Summary of BydbQL Capabilities
+
+| Feature | Streams | Measures
| Top-N | Properties
|
+| :------------------ | :------------------------------------ |
:------------------------------------ | :---------------------------------- |
:---------------------------------- |
+| **Primary Command** | `SELECT ... [FROM STREAM]` | `SELECT ...
[FROM MEASURE]` | `SHOW TOPN ... FROM MEASURE` | `SELECT ...
[FROM PROPERTY]` |
+| **Projection** | Tags by family | Tags & Fields
| Implicit (entity, value) | Flat list of
tags |
+| **Aggregation** | No | Yes (`SUM`,
`MEAN`, etc.) | Yes (optional) | No
|
+| **Grouping** | No | Yes (`GROUP
BY`) | No | No
|
+| **Filtering** | Full `WHERE` clause + `TIME` clause | Full `WHERE`
clause + `TIME` clause | Simple equality `WHERE` + `TIME` clause | `WHERE` by
ID or tags |
+| **Ordering** | Yes (`ORDER BY`) | Yes (`ORDER
BY`) | Yes (`ORDER BY value`) | No
|
+| **Pagination** | Yes (`LIMIT`/`OFFSET`) | Yes
(`LIMIT`/`OFFSET`) | No |
`LIMIT` only |
diff --git a/docs/menu.yml b/docs/menu.yml
index e6eac109..656292f2 100644
--- a/docs/menu.yml
+++ b/docs/menu.yml
@@ -103,6 +103,8 @@ catalog:
path: "/interacting/java-client"
- name: "Data Lifecycle"
path: "/interacting/data-lifecycle"
+ - name: "BydbQL(TBD)"
+ path: "/interacting/bydbql"
- name: "Operation and Maintenance"
catalog:
- name: "Configure BanyanDB"