Workflow Query Examples
Developer guide for the Enezaframework workflow engine. Part of the Workflow series.
Table of Contents
- Overview
- Example 1 — Simple Aggregate Condition
- Example 2 — Multiple Aggregates
- Example 3 — Aggregate + Regular Field
- Example 4 — Groups Format with Annotations
- Example 5 — Programmatic Usage
- Example 6 — Direct use of parse_annotations
- Related Guides
Overview
These examples progress from a single aggregate to groups format and programmatic use. All use the annotation schema from Workflow Aggregate Annotations and the JSON schema from Workflow Query JSON Format.
Example 1 — Simple Aggregate Condition
json
{
"condition": "AND",
"annotations": [
{"function": "sum", "field": "total_amount", "related_model": "lines", "alias": "grand_total"}
],
"rules": [
{"id": "grand_total", "field": "grand_total", "type": "double", "operator": "greater", "value": "5000"}
]
}
SQL equivalent:
sql
SELECT *, SUM(lines.total_amount) AS grand_total
FROM invoice
LEFT JOIN invoice_line AS lines ON lines.invoice_id = invoice.id
GROUP BY invoice.id
HAVING SUM(lines.total_amount) > 5000
Example 2 — Multiple Aggregates
json
{
"condition": "AND",
"annotations": [
{"function": "count", "field": "id", "related_model": "lines", "alias": "item_count"},
{"function": "avg", "field": "unit_price", "related_model": "lines", "alias": "avg_price"}
],
"rules": [
{"id": "item_count", "field": "item_count", "type": "integer", "operator": "greater_or_equal", "value": "5"},
{"id": "avg_price", "field": "avg_price", "type": "double", "operator": "less", "value": "100"}
]
}
Documents with at least 5 line items whose average unit price is below 100.
Example 3 — Aggregate + Regular Field
json
{
"condition": "AND",
"annotations": [
{"function": "sum", "field": "amount", "related_model": "lines", "alias": "total"}
],
"rules": [
{"id": "status", "field": "status", "type": "string", "operator": "equal", "value": "open"},
{"id": "total", "field": "total", "type": "double", "operator": "greater", "value": "1000"}
]
}
Regular model fields and annotation aliases mix freely in the same rules array.
flowchart LR
R["rules[]"] --> F["filter()"]
A["annotations[]"] --> AN["annotate()"]
AN --> F
F --> Q["queryset"]Example 4 — Groups Format with Annotations
json
{
"condition": "AND",
"primary_model": "frameworktestdocument",
"related_models": ["lines"],
"annotations": [
{"function": "max", "field": "amount", "related_model": "lines", "alias": "max_line_amount"},
{"function": "min", "field": "amount", "related_model": "lines", "alias": "min_line_amount"}
],
"groups": [
{
"condition": "AND",
"rules": [
{"id": "max_line_amount", "field": "max_line_amount", "type": "double", "operator": "greater", "value": "500"},
{"id": "min_line_amount", "field": "min_line_amount", "type": "double", "operator": "less", "value": "50"}
]
}
]
}
Documents whose highest line amount exceeds 500 and whose lowest is under 50.
Example 5 — Programmatic Usage
python
from enezaworkflowengine.models import SavedQuery
query = SavedQuery.objects.create(
name="High Value Orders",
content_type=invoice_ct,
filters_json={
"condition": "AND",
"annotations": [
{"function": "sum", "field": "line_total", "related_model": "lines", "alias": "total"},
{"function": "count", "field": "id", "related_model": "lines", "alias": "line_count"},
],
"rules": [
{"id": "total", "field": "total", "type": "double", "operator": "greater", "value": "10000"},
{"id": "line_count", "field": "line_count", "type": "integer", "operator": "greater", "value": "10"},
],
},
user=user,
workflow="InvoiceWorkflow",
)
# Scoped to one document
results = query.get_queryset(object_id="550e8400-e29b-41d4-a716-446655440000")
# All matching records
all_results = query.get_queryset()
Example 6 — Direct use of parse_annotations
python
from enezaworkflowengine.utils import parse_annotations
from myapp.models import Invoice
annotations = parse_annotations(Invoice, [
{"function": "sum", "field": "line_total", "related_model": "lines", "alias": "total"},
{"function": "count", "field": "id", "related_model": "lines", "alias": "line_count"},
])
queryset = Invoice.objects.annotate(**annotations)
queryset = queryset.filter(total__gt=1000, line_count__gte=5)
This bypasses SavedQuery entirely and applies the same aggregate expressions to any queryset.