JsonPath Functions
This page describes how to use the built-in JsonPath support to process event data into projections.
To create useful projections we need to merge the event data with the projection data in different ways. We provide templating support built on JsonPath to support this out-of-the-box.
If the templating support we provide is too restricted for your use-case we encourage you to write your own projector, deployed either as an external function (hosted on eg. AWS) or external service using the Feed API and a storage of your choice. Read more about customized projectors in the next chapter.
The structure of a handler using the provided JsonPath templating looks like this:
1
{
2
"eventType": "<YOUR_EVENT_TYPE>",
3
"functions": [
4
{
5
"function": "merge",
6
"targetSelector": "$.projection",
7
"eventSelector": "$.event"
8
}]
9
}
Copied!
This example will merge the content of the incoming event by using the JsonPath selector $.event with the current state of the projection by targeting the full projection state using the JsonPath selector $.projection.
In a handler function you always have access to $.event (the current event being handled) and $.projection (the current projection state).
Besides that, there is also a $.metadata struct containing the fields aggregateId, timestamp, createdAt and updatedAt.
The above example can also be simplified to:
1
{ "function": "merge" }
Copied!
since the default values for targetSelector and eventSelector are $.event and $.projection, respectively.

Providing raw data

If you have a static value that you want to use as the data for the projection instead of some value that is provided in the event, you can use the rawData argument instead of the eventSelector. You can then provide any JSON value which will be used as-is.
rawData and eventSelector are always mutual exclusive, so make sure you only provide one of them in your function configuration.

Basic object modification

merge

Merges event data with existing projected data.
Argument
Evaluated Type
Required
targetSelector
Object
Yes
eventSelector
Object
No
targetFilter
Not used
No
eventFilter
Not used
No
rawData
Object
No
1
{
2
"eventType": "OrderStatusChangedEvent",
3
"functions": [
4
{
5
"function": "merge"
6
}
7
]
8
}
Copied!

set

Sets/replaces the value of an existing key.
Argument
Evaluated Type
Required
targetSelector
Any
Yes
eventSelector
Any
No
targetFilter
Filter expression
No
eventFilter
Filter expression
No
rawData
Any
No
1
{
2
"eventType": "EmailUpdatedEvent",
3
"functions": [
4
{
5
"function": "set",
6
"targetSelector": "$.projection.user.email",
7
"eventSelector": "$.event.newEmail"
8
}
9
]
10
}
Copied!

unset

Removes an existing key.
Argument
Evaluated Type
Required
targetSelector
Any
Yes
eventSelector
Not used
No
targetFilter
Filter expression
No
eventFilter
Filter expression
No
rawData
Not used
No
1
{
2
"eventType": "EmailRemovedEvent",
3
"functions": [
4
{
5
"function": "unset",
6
"targetSelector": "$.projection.user.email"
7
}
8
]
9
}
Copied!

clear

Clear the entire projection or a specific field, i.e reset it to a default value.
Data type
Default value
String
""
Boolean
false
Number
0
Array
[]
Object
{}
Argument
Evaluated Type
Required
targetSelector
Any
No
eventSelector
Not used
No
targetFilter
Filter expression
No
eventFilter
Filter expression
No
rawData
Not used
No
1
{
2
"eventType": "ListClearedEvent",
3
"functions": [
4
{
5
"function": "clear",
6
"targetSelector": "$.projection.todoList"
7
}
8
]
9
}
Copied!

delete

Delete a projection instance entirely. Future requests will result in a 404 Not Found.
Argument
Evaluated Type
Required
targetSelector
Not used
No
eventSelector
Not used
No
targetFilter
Not used
No
eventFilter
Filter expression
No
rawData
Not used
No
1
{
2
"eventType": "UserDeletedEvent",
3
"functions": [
4
{
5
"function": "delete"
6
}
7
]
8
}
Copied!

Working with arrays/lists

append

Adds anything to the end of an array.
Argument
Evaluated Type
Required
targetSelector
Array
Yes
eventSelector
Any
No
targetFilter
Filter expression
No
eventFilter
Filter expression
No
rawData
Any
No
1
{
2
"eventType": "RunnerFinishedRaceEvent",
3
"functions": [
4
{
5
"function": "append",
6
"targetSelector": "$.projection.finishers",
7
"eventSelector": "$.event['runnerName','finishTime']"
8
}
9
]
10
}
Copied!

prepend

Adds anything to the beginning of an array.
Argument
Evaluated Type
Required
targetSelector
Array
Yes
eventSelector
Any
No
targetFilter
Filter expression
No
eventFilter
Filter expression
No
rawData
Any
No
1
{
2
"eventType": "TodoAddedEvent",
3
"functions": [
4
{
5
"function": "prepend",
6
"targetSelector": "$.projection.todos",
7
"eventSelector": "$.event['todoId','todoText']"
8
}
9
]
10
}
Copied!

remove

Removes an existing key or an array element matching filter expression.
Argument
Evaluated Type
Required
targetSelector
Any
Yes
eventSelector
Not used
No
targetFilter
Filter expression
Yes
eventFilter
Not used
No
rawData
Not used
No
1
{
2
"eventType": "TodoRemovedEvent",
3
"functions": [
4
{
5
"function": "remove",
6
"targetSelector": "$.projection.todos[?]",
7
"targetFilter": "[?(@.todoId == $.event.todoId)]"
8
}
9
]
10
}
Copied!

Performing arithmetic

add

Sums two numbers together.
Argument
Evaluated Type
Required
targetSelector
Number
Yes
eventSelector
Number
No
targetFilter
Not used
No
eventFilter
Not used
No
rawData
Number
No
1
{
2
"eventType": "OrderPlacedEvent",
3
"functions": [
4
{
5
"function": "add",
6
"targetSelector": "$.projection.totalAmount",
7
"eventSelector": "$.event['orderAmount']"
8
}
9
]
10
}
Copied!

subtract

Subtracts two numbers.
Argument
Evaluated Type
Required
targetSelector
Number
Yes
eventSelector
Number
No
targetFilter
Not used
No
eventFilter
Not used
No
rawData
Number
No
1
{
2
"eventType": "OrderRefundedEvent",
3
"functions": [
4
{
5
"function": "subtract",
6
"targetSelector": "$.projection.totalAmount",
7
"eventSelector": "$.event['orderAmount']"
8
}
9
]
10
}
Copied!

inc

Increases a number by one.
Argument
Evaluated Type
Required
targetSelector
Number
Yes
eventSelector
Not used
No
targetFilter
Filter expression
No
eventFilter
Not used
No
rawData
Not used
No
1
{
2
"eventType": "TicketReservedEvent",
3
"functions": [
4
{
5
"function": "inc",
6
"targetSelector": "$.projection.ticketCount"
7
}
8
]
9
}
Copied!

dec

Decreases a number by one.
Argument
Evaluated Type
Required
targetSelector
Number
Yes
eventSelector
Not used
No
targetFilter
Filter expression
No
eventFilter
Not used
No
rawData
Not used
No
1
{
2
"eventType": "TicketReleasedEvent",
3
"functions": [
4
{
5
"function": "dec",
6
"targetSelector": "$.projection.ticketCount"
7
}
8
]
9
}
Copied!

Adding lookup via references

You can make your projections

setref

Marks a projection field as a reference which makes it filterable in the API.
Argument
Evaluated Type
Required
targetSelector
String/Number/Date
Yes
eventSelector
Not used
No
targetFilter
Not used
No
eventFilter
Not used
No
rawData
Not used
No
1
{
2
"eventType": "TicketReleasedEvent",
3
"functions": [
4
{
5
"function": "setref",
6
"targetSelector": "$.projection.releaseDate"
7
}
8
]
9
}
Copied!

clearref

Clears the reference for the projection, removing the ability to filter.
Argument
Evaluated Type
Required
targetSelector
Not used
No
eventSelector
Not used
No
targetFilter
Not used
No
eventFilter
Not used
No
rawData
Not used
No
1
{
2
"eventType": "TicketReleasedEvent",
3
"functions": [
4
{
5
"function": "clearref"
6
}
7
]
8
}
Copied!

Filters

Functions can also provide two filters: targetFilter and eventFilter.
To add a filter to a selector you provide a [?] in the selector text, as described in the JsonPath documentation. The filter for the selector is then applied for the given function. This is useful for matching on ids in nested lists or to apply conditional logic for when/how to process events.
All Filter Operators that are described here are supported.
Last modified 1yr ago