Realtime Event Filtering¶
Filter realtime events to receive only the data you need. Reduce noise, save bandwidth, and simplify your event handlers.
Overview¶
Centrali Realtime supports three levels of filtering:
- Structure filtering - Only events from specific structures
- Event type filtering - Only specific event types (create, update, delete)
- Data filtering (CFL) - Filter by record field values
Structure Filtering¶
Receive events only from specific structures:
centrali.realtime.subscribe({
structures: ['order', 'invoice'], // Only these structures
onEvent: handleEvent
});
Leave empty to receive events from all structures:
centrali.realtime.subscribe({
// structures: [], // or omit entirely
onEvent: handleEvent // Receives all structure events
});
Event Type Filtering¶
Filter by event type:
centrali.realtime.subscribe({
events: ['record_created'], // Only new records
onEvent: handleEvent
});
// Multiple event types
centrali.realtime.subscribe({
events: ['record_created', 'record_updated'], // Creates and updates only
onEvent: handleEvent
});
Available event types: - record_created - New record created - record_updated - Record modified - record_deleted - Record deleted
Data Filtering with CFL¶
Centrali Filter Language (CFL) v1 lets you filter events based on record data values.
Event Data Structure¶
The data field structure differs by event type:
| Event Type | Data Structure | Filter Path |
|---|---|---|
record_created | { field1, field2, ... } | data.field1 |
record_updated | { before: {...}, after: {...} } | data.after.field1 or data.before.field1 |
record_deleted | { field1, field2, ... } | data.field1 |
For record_updated events, use data.after.* to filter on the new values or data.before.* to filter on the old values.
Basic Syntax¶
Examples¶
// Simple equality
centrali.realtime.subscribe({
structures: ['order'],
filter: 'data.status:shipped', // Only shipped orders
onEvent: handleEvent
});
// Numeric comparison
centrali.realtime.subscribe({
structures: ['order'],
filter: 'data.total:gt:1000', // Orders over $1000
onEvent: handleEvent
});
// String matching
centrali.realtime.subscribe({
structures: ['customer'],
filter: 'data.email:endswith:@company.com', // Company emails only
onEvent: handleEvent
});
Supported Operators¶
| Operator | Description | Example |
|---|---|---|
eq | Equals (default) | data.status:shipped or data.status:eq:shipped |
ne | Not equals | data.status:ne:cancelled |
gt | Greater than | data.amount:gt:100 |
lt | Less than | data.amount:lt:50 |
gte | Greater than or equal | data.priority:gte:5 |
lte | Less than or equal | data.quantity:lte:10 |
in | Value in list | data.status:in:pending,processing,shipped |
nin | Value not in list | data.status:nin:cancelled,refunded |
contains | Contains substring | data.name:contains:test |
startswith | Starts with prefix | data.sku:startswith:PROD- |
endswith | Ends with suffix | data.email:endswith:@example.com |
Nested Fields¶
Access nested object fields using dot notation:
// Record data: { address: { city: "New York", country: "US" } }
filter: 'data.address.city:New York'
filter: 'data.address.country:in:US,CA,UK'
Data Types¶
CFL automatically handles type conversion:
Strings:
Numbers:
Booleans:
Combining Filters¶
You can combine structure, event, and data filters:
centrali.realtime.subscribe({
structures: ['order'], // Only orders
events: ['record_created'], // For creates, filter on data directly
filter: 'data.status:in:shipped,delivered',
onEvent: handleEvent
});
// For updates, filter on data.after (the new state)
centrali.realtime.subscribe({
structures: ['order'],
events: ['record_updated'],
filter: 'data.after.status:in:shipped,delivered',
onEvent: handleEvent
});
Filter evaluation order: 1. Structure filter (client-side for efficiency) 2. Event type filter (server-side) 3. CFL data filter (server-side)
Events must pass all filters to be delivered.
Use Cases¶
High-Value Orders Dashboard¶
centrali.realtime.subscribe({
structures: ['order'],
events: ['record_created'],
filter: 'data.total:gte:500',
onEvent: (event) => {
showNotification(`High-value order: $${event.data.total}`);
}
});
Status Change Notifications¶
// For update events, data contains { before, after } objects
centrali.realtime.subscribe({
structures: ['shipment'],
events: ['record_updated'],
filter: 'data.after.status:in:in_transit,delivered',
onEvent: (event) => {
const { before, after } = event.data;
notifyCustomer(after.customerId, after.status);
}
});
Regional Data¶
centrali.realtime.subscribe({
structures: ['store'],
filter: 'data.region:west_coast',
onEvent: handleWestCoastStoreEvent
});
VIP Customer Activity¶
centrali.realtime.subscribe({
structures: ['customer', 'order'],
filter: 'data.tier:premium',
onEvent: (event) => {
logVIPActivity(event);
}
});
Performance Considerations¶
Filter Early¶
Apply the most restrictive filters to reduce data transfer:
// Good - filter on server
centrali.realtime.subscribe({
structures: ['order'],
filter: 'data.status:pending',
onEvent: handlePendingOrders
});
// Less efficient - filtering in handler
centrali.realtime.subscribe({
structures: ['order'],
onEvent: (event) => {
if (event.data.status === 'pending') { // Filtering client-side
handlePendingOrders(event);
}
}
});
Use Specific Structures¶
Always specify structures when possible:
Limitations¶
Single CFL Expression¶
Currently, only one CFL filter expression is supported per subscription. For complex filtering:
// Option 1: Multiple subscriptions
const sub1 = centrali.realtime.subscribe({
filter: 'data.status:pending',
onEvent: handlePending
});
const sub2 = centrali.realtime.subscribe({
filter: 'data.status:processing',
onEvent: handleProcessing
});
// Option 2: Use 'in' operator
centrali.realtime.subscribe({
filter: 'data.status:in:pending,processing',
onEvent: (event) => {
if (event.data.status === 'pending') handlePending(event);
else handleProcessing(event);
}
});
No Logical Operators¶
CFL v1 doesn't support AND/OR operators. Use multiple subscriptions or client-side filtering for complex logic.
Case Sensitivity¶
String comparisons for contains, startswith, and endswith are case-insensitive. Equality checks (eq) are case-sensitive.
Error Handling¶
Invalid filter expressions return a 400 error:
centrali.realtime.subscribe({
filter: 'invalid::filter', // Malformed
onError: (error) => {
// error.code will be 'CONNECTION_ERROR'
// Check server response for details
console.error('Filter error:', error.message);
},
onEvent: handleEvent
});
Related Documentation¶
- Quickstart - Get started with realtime
- Query Guide - Query syntax for fetching records
- API Reference - HTTP API details