synthtraffic Get started
Docs menu

Expressions

Collections

An order with line items is one event containing a list. Collection functions build that list, read its fields, and reshape related objects.

The result

{"items":[{"lineNumber":1,"product":"keyboard","unitPrice":25,"quantity":2,"lineTotal":50},{"lineNumber":2,"product":"mouse","unitPrice":15,"quantity":2,"lineTotal":30}],"itemCount":2,"subtotal":80,"averageUnitPrice":20}

Build line items and totals

YAML order-collections.yaml
generators:
  - name: orders
    config:
      maxEvents: 1
    value:
      items:
        =array:
          count: 2
          of:
            lineNumber: =seq(start=1)
            product: =cycle(keyboard, mouse)
            unitPrice: =cycle(25, 15)
            quantity: 2
            lineTotal: =multiply($unitPrice, $quantity)
      itemCount: =count($items)
      subtotal: =sum($items.lineTotal)
      averageUnitPrice: =avg($items.unitPrice)

array block

Generates a list of structured items. count must evaluate to a non-negative integer, and of must be an object.

items:
  =array:
    count: =int(1, 4)
    of:
      productId: =uuid()
      unitPrice: =uniform(10, 100, round=2)
      quantity: =int(1, 5)
{"items":[{"productId":"60b7529e-bf1f-4b5e-8b70-a7b5d26b30aa","unitPrice":11.49,"quantity":1},{"productId":"1d267630-784e-472d-8995-c3154c000c40","unitPrice":14.33,"quantity":4}]}

Each item has its own field scope, so $unitPrice and $quantity refer to the current item. Stateful expressions such as seq and cycle continue across items.

merge

Merges one or more objects. Later values replace earlier values for the same key without changing that key’s original position.

profile: =merge($baseProfile, $auditFields)

With baseProfile: {name: Asha, plan: starter} and auditFields: {plan: plus, createdAt: 2026-01-02T03:04:05Z}:

{"profile":{"name":"Asha","plan":"plus","createdAt":"2026-01-02T03:04:05Z"}}

Block form:

profile:
  =merge:
    - id: =uuid()
    - createdAt: =now()
{"profile":{"id":"587bd559-6726-42b9-b959-411ecbfa3bec","createdAt":"2026-01-02T03:04:05Z"}}

Every input must be an object.

selectKeys and omitKeys

selectKeys keeps the named keys. omitKeys removes them. Both preserve source-field order, and both ignore requested keys that are missing.

summary: =selectKeys($customer, [customerId, name])
publicCustomer: =omitKeys($customer, [internalScore])

Compact form with a YAML list is invalid: selectKeys treats each list item as another positional argument. Use block form:

summary:
  =selectKeys:
    from: $customer
    keys: [customerId, name]
{"summary":{"customerId":"CUST-01","name":"Asha Rao"}}
publicCustomer:
  =omitKeys:
    from: =ref(customers)
    keys: [internalScore, auditFlags]
{"publicCustomer":{"customerId":"CUST-01","name":"Asha Rao"}}

range(start, end, step?)

Returns integers from start toward, but not including, end. step defaults to 1 and cannot be zero.

ids: =range(1, 5)
even: =range(2, 8, step=2)
down: =range(5, 1, step=-2)
{"ids":[1,2,3,4],"even":[2,4,6],"down":[5,3]}

When the step points away from the end, the result is an empty list.

sum(list), count(list), avg(list)

Reduce one list to one value.

lineCount: =count($lineItems)
total: =sum($lineItems.price)
averagePrice: =avg($lineItems.price)

With lineItems prices 10, 20, and 30:

{"lineCount":3,"total":60,"averagePrice":20}

sum and avg require numeric items. For an empty list, sum and count return 0; avg returns null. sum and avg accept round=N.

$lineItems.price projects the price field from every item before the aggregate runs. Use min($lineItems.price) or max($lineItems.price) for numeric bounds; those functions are documented under Math.

For the beginner line-item lesson, see Collections in Build a scenario.

Next: link events with ref and previous.