← Back to all posts
8 min readCentrali Team

Smart Queries 3.0: Variables, Joins, and a Better Developer Experience

Smart Queries get a major upgrade with parameterized variables, flexible record ID joins, and a cleaner result structure. Build dynamic, reusable queries that accept runtime parameters.

ProductFeatureAnnouncement

Smart Queries have always been one of Centrali's most powerful features—define complex filters once, save them, and execute programmatically via API or SDK. Today, we're making them even more powerful with Centrali 3.0.

What's New in Smart Queries 3.0

Parameterized Variables

The most requested feature is here: variables. Instead of hardcoding filter values, use mustache-style {{variableName}} placeholders and provide values at execution time.

Before (static query):

json
{ "where": { "userId": { "$eq": "user_123" }, "status": { "$eq": "active" } } }

After (dynamic query):

json
{ "where": { "userId": { "$eq": "{{currentUserId}}" }, "status": { "$eq": "{{statusFilter}}" } } }

Execute with any values:

typescript
const results = await centrali.smartQueries.execute('orders', 'my-query', { variables: { currentUserId: 'user_456', statusFilter: 'pending' } });

Variables work in any operator—$eq, $gt, $in, $contains, and more. The system validates variable names and returns helpful errors if you forget to provide a required value.

Record ID Joins with _recordId

Joining structures just got easier. Use the special _recordId field to join on actual record UUIDs instead of data fields.

Common pattern: Your order-items structure stores a productId field containing the UUID of a product record. Join them like this:

json
{ "select": ["quantity", "unitPrice"], "join": { "foreignSlug": "products", "localField": "productId", "foreignField": "_recordId", "select": ["name", "category", "basePrice"] } }

This translates to a SQL join on r1.data->>'productId' = r2.id—exactly what you need for foreign key relationships.

Nested _joined Results

Joined data now returns in a clean, predictable structure. Instead of flat prefixed fields, you get a nested _joined object—consistent with how _expanded works for reference fields.

Result structure:

json
{ "quantity": 5, "unitPrice": "29.99", "_joined": { "products": { "name": "Wireless Headphones", "category": "Electronics", "basePrice": "24.99" } } }

Access joined data with:

typescript
items.forEach(item => { console.log(`${item.quantity}x ${item._joined?.products?.name}`); });

Filter Joined Records with joinWhere

Need to filter based on the joined table? Use joinWhere to apply conditions to joined records:

json
{ "select": ["sku", "inventory"], "join": { "foreignSlug": "products", "localField": "productId", "foreignField": "_recordId", "select": ["name", "inventoryTracking"] }, "joinWhere": { "inventoryTracking": { "$eq": true } } }

This returns only items where the joined product has inventory tracking enabled.

Visual Builder Support

All these features work in the Smart Query visual builder too:

  • Variables: Define them in conditions and see detected variables highlighted
  • Joins: Toggle JOIN on, select the foreign structure, and pick fields to include
  • Join Where: Add filter conditions on joined record fields

When you click "Run Query" with variables, a modal prompts you for values before executing.

SDK Support

The SDK fully supports all new features:

typescript
// Execute with variables const results = await centrali.smartQueries.execute('orders', 'query-id', { variables: { userId: 'user_123', minAmount: '100' } }); // Access joined data results.data.forEach(order => { const customer = order._joined?.customers; console.log(`Order for ${customer?.name}: ${order.total}`); });

Migration Notes

Breaking change: If you were relying on flat prefixed field names for joins (e.g., product_name), update your code to use the nested _joined structure (e.g., _joined.products.name).

Queries without joins are unaffected.

Get Started

Smart Queries 3.0 is available now for all Centrali workspaces. Check out the Smart Queries documentation for detailed examples and API reference.


Questions or feedback? Reach out on Discord or email us.

Building something with Centrali and want to share feedback about this feature?

Email feedback@centrali.io