POST /combined/¶
Executes a multi-stage pipeline query: JOIN → SELECT → AGGREGATE in a single request. Each stage is optional. Stages execute in order and feed their output into the next stage.
Request¶
Query Parameters:
| Parameter | Description |
|---|---|
db_name |
Name of the database |
Body:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
namespace |
string | ❌* | — | Namespace for non-join queries. Required if join is not provided |
join |
object | ❌ | — | JOIN configuration (see /join/ docs). If omitted, loads namespace directly |
select |
object | ❌ | — | SELECT/filter configuration (see /select/ docs) |
aggregate |
object | ❌ | — | AGGREGATE configuration (see /aggregate/ docs) |
convert_types |
bool | ❌ | true |
Auto-convert string values to int/float where possible |
At least one of join, select, or aggregate must be provided.
Behavior¶
Execution order:
- JOIN — if provided, joins two namespaces into a combined dataset. Otherwise loads
namespacedirectly. - SELECT — if provided, applies WHERE filters, column projection, DISTINCT, ORDER BY, LIMIT, and OFFSET to the current dataset.
- AGGREGATE — if provided, applies pre-filters, GROUP BY, aggregations, HAVING, ORDER BY, and LIMIT to produce grouped results.
Each stage receives the output of the previous stage as its input, enabling complex pipelines in a single API call.
Responses¶
200 OK — rows result (no aggregate)¶
{
"result_type": "rows",
"total_rows": 5,
"execution_time_ms": 31.2,
"stages": [
{ "stage": "join", "rows_output": 9, "time_ms": 18.1 },
{ "stage": "select", "rows_output": 5, "time_ms": 2.4 }
],
"rows": [
{ "emp.name": "Alice", "emp.department": "Engineering", "ord.product": "Laptop", "ord.amount": 2500 }
]
}
200 OK — aggregated result¶
{
"result_type": "aggregated",
"total_groups": 3,
"execution_time_ms": 42.7,
"stages": [
{ "stage": "join", "rows_output": 9, "time_ms": 18.1 },
{ "stage": "select", "rows_output": 9, "time_ms": 1.2 },
{ "stage": "aggregate", "groups": 3, "time_ms": 0.8 }
],
"groups": [
{ "emp.department": "Engineering", "order_count": 4, "total_spend": 5270 }
]
}
| Field | Description |
|---|---|
result_type |
"rows" or "aggregated" |
stages |
Execution trace showing rows/groups and time per stage |
rows |
Present when result_type is "rows" |
groups |
Present when result_type is "aggregated" |
Error Responses¶
| Status | Condition |
|---|---|
400 |
No operations specified, or namespace missing when join not provided |
404 |
Namespace not found |
500 |
Unexpected internal error |
Notes¶
- The
stagesarray in the response is useful for performance debugging — it shows exactly how many rows/groups each stage produced and how long it took. convert_typesis applied at the end for row results only. Aggregated results are always numeric.- ORDER BY in the SELECT stage uses stable sort — multiple ORDER BY fields are supported.
Example¶
import requests
SERVER_URL = "http://18.220.128.24:8000"
API_KEY = "yourapitoken"
def combined(db_name: str, query: dict) -> dict:
response = requests.post(
f"{SERVER_URL}/combined/",
headers={"X-API-Key": API_KEY},
params={"db_name": db_name},
json=query,
)
response.raise_for_status()
return response.json()
# Join employees + orders, filter completed orders, aggregate spend by department
result = combined("my_db", {
"join": {
"left_namespace": "employees",
"right_namespace": "orders",
"join_type": "inner",
"join_conditions": [{"left_field": "id", "right_field": "employee_id", "operator": "eq"}],
"left_prefix": "emp",
"right_prefix": "ord",
},
"select": {
"where": [{"field": "ord.status", "operator": "eq", "value": "completed"}]
},
"aggregate": {
"group_by": ["emp.department"],
"aggregations": [
{"field": "ord.order_id", "operation": "count", "alias": "order_count"},
{"field": "ord.amount", "operation": "sum", "alias": "total_spend"},
],
"order_by": ["-total_spend"],
},
})
print(result)