Skip to content

Compose Query Chain API Manual

Status: 8.x synchronized edition. Positioning: Chain-style API reference for Query.from(...).where(...).select(...) users. Primary AI path: For MCP and AI generation, prefer the JSON-first DSL Manual. The chain API is a mirror for developers who prefer method chaining.

1. Relationship with the DSL Manual

The DSL manual and this chain API manual must be functionally equivalent, but the syntax is intentionally different:

CapabilityDSL formChain form
Base querydsl({ model, columns, slice })Query.from(model).where(...).select(...)
Derived querydsl({ model: prevPlan, ... })continue from prevPlan or wrap it as a source
Joinleft.join(right, type, on)same plan method
Unionleft.union(right, options)same plan method
timeWindowtop-level timeWindow objecthelper may exist, but DSL form is the stable public AI contract
CTE reusecompiler-managedcompiler-managed

2. Minimal Chain Query

javascript
const sales = Query.from("FactSalesQueryModel")
  .where([{ field: "salesDate$id", op: ">=", value: "2025-01-01" }])
  .select("product$id", "sum(salesAmount) as totalSales")
  .groupBy("product$id")
  .orderBy("-totalSales")
  .limit(100);

return {
  plans: { top_sales: sales }
};

3. Public Boundaries

  • Chain API is not the recommended shape for AI prompt generation.
  • Do not hand-write SQL or CTE text.
  • CTE reuse is compiler-managed when the same plan is reused by downstream plans.
  • Do not use chain helpers to bypass dataset.query_model boundaries. Single-model pivot and single-model time-window analysis remain dataset.query_model payload features.

4. Derived Query

javascript
const base = Query.from("FactSalesQueryModel")
  .select("product$id", "sum(salesAmount) as totalSales")
  .groupBy("product$id");

const filtered = base
  .where([{ field: "totalSales", op: ">", value: 100000 }])
  .select("product$id", "totalSales")
  .orderBy("-totalSales");

The derived layer can only reference columns projected by the previous plan.

5. Join

javascript
const joined = customers.join(orders, "left", [
  { left: "id", op: "=", right: "customerId" }
]);

Boundaries:

  • Supported types: inner, left, right, full where the dialect supports them.
  • Conditions are equality-based and combined with AND.
  • Cross-datasource Join is not part of the public contract.
  • Rename same-name columns before joining or before final projection.

6. Union

javascript
const allOrders = online.union(offline, { all: true });

Union uses the left-side schema. Branches must expose compatible columns with the same business meaning.

7. CTE Reuse

If a plan is reused by multiple downstream plans, the compiler may generate a shared CTE on supported dialects:

javascript
const productSales = Query.from("FactSalesQueryModel")
  .select("product$id", "sum(salesAmount) as totalSales")
  .groupBy("product$id");

const highValue = productSales.where([
  { field: "totalSales", op: ">", value: 100000 }
]);

const ranked = productSales.orderBy("-totalSales").limit(20);

Public boundaries:

  • Users do not name SQL CTEs.
  • Named top-level plans are only result-map keys.
  • Recursive CTE and arbitrary SQL CTE injection are not supported.

8. timeWindow

For stable AI and MCP usage, prefer the DSL shape:

javascript
dsl({
  model: "FactSalesQueryModel",
  columns: ["salesDate$id", "salesAmount"],
  groupBy: ["salesDate$id"],
  timeWindow: {
    field: "salesDate$id",
    grain: "month",
    comparison: "yoy",
    targetMetrics: ["salesAmount"]
  }
});

Execution order is the same as in the DSL manual: expand time-window metrics first, then apply post-window scalar calculated fields.

Maintenance

DateChangeNotes
2026-05-03Added English synchronized pageMirrors the chain API contract and points AI generation to the DSL manual