Derived data rule language
Learn about the derived data rule language and parameters.
An example rule
{
"name":"my DD rule", // required; unique in tenant
"ruleType": "derived", // required
"isGloballyVisible": false, // optional; default=false
"createdAt": "2020-12-11T12:01:48Z", // generated; readonly
"updatedBy": "fe820f40-35ae-4c92-a09b-62c35bbec155", // generated; readonly
"tenantId": "1aaeef92-7eca-47ea-9545-d9b3a6c27416", // optional; default=global
"ruleId": "40950af9-1f6b-46c2-ac32-7cbec25464b1", // generated; readonly
"version": 1.0, // generated; readonly
"updatedAt": "2020-12-11T12:01:48Z", // generated; readonly
"status": { // generated; readonly
"code": "live",
"details": "Version 1.0 of this rule is live and processing"
},
"fieldsSetByRule":[ // generated; readonly
{
"fieldName":"",
"fieldType":""
},
{
"fieldName":"",
"fieldType":""
},
...
],
"objectTypeSetByRule": "Issue", // generated; readonly
"instructions":{ // required
"enableCollapse": true, // optional; default=false
"throttling": { // optional
"window": "15.minutes",
"enabled": "false"
},
"ifEvent": { // required
"AND": [ // root-level
{
"EQUALS": [
{
"SELECT": "",
"TYPE": "String"
},
{
"VALUE": "",
"TYPE": "String"
}
]
},
{
"OR": [
{
"EXISTS": [
{
"SELECT": "",
"TYPE": "String"
}
]
},
{
"EXISTS": [
{
"SELECT": "",
"TYPE": "String"
}
]
}
]
}
]
},
"sendObjectUpsertEvents": { // required
"objects": {// required
"id": { // required
"select": ""
},
"type": { // required
"select": ""
}
},
"map": [ // required
{
"sequence": "1",
"expression":{ // required
"QUERY": {// optional
"hint": "objectwarehouse-adhoc", // required
"advancedFilter": { // optional
"AND": [
{
"EQUALS": [
{
"FIELD": "", // optional
"TYPE": "" // required
},
{
"TYPE": "",
"SELECT": ""
}
]
},
{
"EQUALS": [
{
"FIELD": "",
"TYPE": "String"
},
{
"VALUE": "", // optional
"TYPE": "String"
}
]
}
]
},
"reduce": { // optional
"expression": { // required
"fieldPath": "",
"operator": "SUM"
},
"output_local": { // required
"resultAlias": ""
}
}
}
}
},
{
"sequence": 2, // required
"nestedUpserts": { // optional
"nestedPath": "", // required
"objects": {
"localIdentifiers": {
"SELECT": "localIdentifiers"
}
},
"map": [ // required
{
"sequence": 1,
"expression": {
"QUERY": {
"hint": "orderflow",
"output_local": {
"fields": [
...
],
"resultAlias": ""
}
}
}
},
{
"sequence": 2,
"output": {
"resultFieldPath": "",
"resultType": "String"
},
"if": {// optional
"AND": [
{
"EQUALS": [
{
"SELECT_LOCAL": "",
"TYPE": "String"
},
{
"VALUE": "value",
"TYPE": "String"
}
]
},
{
"GREATER_THAN": [
{
"SELECT_LOCAL": "",
"TYPE": "float"
},
{
"VALUE": 0,
"TYPE": "float"
}
]
}
]
},
"expression": {
"value": "value",
"type": "String"
},
"breakOnMatch": true // optional
},
{
"sequence": 3,
"output": {
"resultFieldPath": "",
"resultType": "String"
},
"expression": {
"minus": [ // optional
{
"SELECT_LOCAL": "",
"TYPE": "Date"
},
{
"SELECT_LOCAL": "",
"TYPE": "float"
}
]
}
}
]
}
}
]
}
}
Where:
- isGloballyVisible
- Optional Boolean value that indicates whether this rule filter event by
tenantId. Default value isfalse.
- fieldsSetByRule
- Array of JSON objects and each object contains the
fieldNameandfieldType.Generated by the suite, the array is collected from
outputin the top level of each map section. - objectTypeSetByRule
- A string that indicates the object type that the derived data rule upserts. Generated by the suite.
- Rule instructions documentation
-
"instructions: { - enableCollapse
- Optional Boolean value that specifies whether this rule needs to merge the related events with
same business object ID in the same batch into one output event, which also can improve performance.
Default value is
false. - throttling
- Optional time window that specifies the interval to trigger derived data rule. By default,
Derived Data rule is triggered by
event. But after you enable the time window, the rule will be triggered byinterval, and the events in different intervals will be processed in batches, which also can improve performance."throttling": { - window
- Required string value that specifies timer. The format must be
integer.timeUnit, for example"1.minute","15.minutes","2.m". Time unit must be insecond, minute, hour, dayor"s","m","h","d". For example,"window" : "15.minutes"means that this rule is triggered at :15, :30, :45 and :00 every hour. - enabled
- Required Boolean that specifies whether to enable throttling. Default value is
false."enabled": } - ifEvent
-
Required initial event that specifies filter conditions. The operator must be in the list of
EXISTS, GREATER_THAN, GREATER_EQUALS, LESS_THAN, LESS_EQUALS, EQUALS, UNEQUALS, OR, AND, POINTS_IN_CIRCLES, REFERENCED_BY.Required string that specifies one from
SELECTandVALUEin every operand and must indicateTYPEfor the field you want to select or value you specified.TYPE,SELECT, andVALUEare case-insensitive.SELECTallowing field and field path."ifEvent": { operator:[ { operator: [ operand, operand ] }, { operator: [ operand, operand ] } ] }
- sendObjectUpsertEvents
- Required object for processing and sending the
result.
"sendObjectUpsertEvents": {
- objects
- Required object that specifies the fields that you want to get from the initial event.
Can specify only fields
"id"and"type"insendObjectUpsertEvents.object."objects": { - id
- Required object that specifies the event
ID.
"id": { - select
- Required string that specifies the field path of the event, can be separated by a period (.).
For example,
"select": "a.b.c""select": "" } - type
- Required string that specifies the event
type.
"type": { - select
- Required string that specifies the field path of the event.
"select": "" } } - map
- Required array that specifies how to process events to get derived data. It also supports
nestedUpsertsto handle the event with multiple line-level events.Allowing these fields in every map element.
Property Type Required sequencestring Yes expressionstring Yes nestedUpsertsobject No ifobject No outputobject No breakOnMatchstring No "map":[ { - sequence
- Required string that specifies a number for every element of the map array. Statement blocks are
executed in ascending order based on the specified sequence
number.
"sequence": "" - output
- Optional object that specifies where you want to output result, allows field path format, such
as
a.b.cor arraya[name=globalIdentifiersTest].b"output": {
- resultFieldPath
- Required string that supports output object or array. Object needs to specify the path, such as
a.b.c. Array needs to specify the array path, such asa[name=nameValue].b. When the output is an array, an element in the array is located based on the name, so the name must be unique in the array."resultFieldPath": "a.b.c", //object "resultFieldPath":"globalIdentifiers[name=globalIdentifiersTest].value", //array - resultType
- Required string that specifies output data type. The value must be in
int, long, double, float, String, Date, Boolean, Object, Array."resultType":"string" - expression
- Required object expression that allows
QUERY,CONCATENATE, mathoperatorand specifiesVALUEdirectly.The math operator in the root-level needs to be in the list of
MULTIPLY, DIVIDE, ADD, SUBTRACT, MOD, MIN, MAX, ABS, SQRT, ROUND.The operator in the second level supports more types, including
MULTIPLY, DIVIDE, ADD, SUBTRACT, MOD, MIN, MAX, ABS, SQRT, ROUND, SELECT, SELECT_LOCAL, VALUE.Note: TheSELECT_LOCALoperator is used to query the fields that are saved in a temporary file. For example, the fields are saved in cache after theexpression.QUERY.output_localis executed."expression": { - CONCATENATE
-
Optional
CONCATENATEarray that can support one or more elements. Each element in the array supportsselect,select_local,value.CONCATENATEconcatenates the calculation results of each element in the order of the array as the calculation result of the expression."expression":{ "CONCATENATE":[ // optional { "SELECT":"timestampEventRecieved", "TYPE":"String", "ORDER": 1 }, { "SELECT_LOCAL":"lineCountsByShipmentStatus.FULLY_SHIPPED", "TYPE":"String", "ORDER": 2 }, { "VALUE":"ddRuleTestId12345666", "TYPE":"String", "ORDER": 3 } ] }
- QUERY
- Optional object query from the specified
index.
"QUERY": {
- hint
- Required string that specifies the index that you want to
query.
"hint":""
- advancedFilter
- Optional object that specifies query conditions to filter event from the specified index. The
definition of
advancedFilterhere is same as theadvancedFilterGraphQL query. Theoperatormust be in the list ofCONTAINS, CONTAINS_ANY, EXISTS, GREATER_THAN, GREATER_EQUALS, LESS_THAN, LESS_EQUALS, EQUALS, EQUALS_ANY, UNEQUALS, NOT, OR, AND, POINTS_IN_CIRCLES, REFERENCED_BY.Required string that specifies one from
FIELD,SELECT, andVALUEin every operand and must indicateTYPEfor the field that you want to select or the value that you specified."advancedFilter": { operator:[ { operator: [ operand, operand ] }, { operator: [ operand, operand ] } ] } - reduce
- Optional object to get derived data by using a math operator. Can save calculation result to a
temporary file or send to consume
directly.
"reduce": { - expression
- Required object expression that can contain a math
operator.
"expression": { - fieldPath
-
Required string that specifies a field path in the event. Format is same as preceding field path definition, such as
a.b.c.If you want to do aggregation on name value pairs, you must use the following format.
"a.b[name=some-value].value"For example, you want to do aggregation on the value of the name value pairs in the following name value pairs in
orderLines.{ "values": [ { "name": "amount", "value": 111 } ], .... }The following example shows the
fieldPath."orderLines.values[name=amount].value""fieldPath": ""
- operator
- Required string that specifies the math operator that you want to use.
The operator must be in list of
"COUNT", "COUNT_DISTINCT", "SUM", "STD_DEVIATION_UPPER_BOUND", "STD_DEVIATION_LOWER_BOUND"."operator": "" }The following example shows the operator
"STD_DEVIATION_UPPER_BOUND", "STD_DEVIATION_LOWER_BOUND"."operator": "", "numberOfDeviationsInBound": 3The
numberOfDeviationsInBoundparameter controls how many standard deviations from the mean to display.numberOfDeviationsInBoundcan be any nonnegative double, which means that you can request noninteger values, such as 1.5. A value of 0 is valid but returns the average for both upper and lower bounds. The upper and lower bounds are calculated as population metrics, so they are always the same asupper_populationandlower_populationrespectively.
- output_local
- Required object that specifies the name of the result or fields that you want to save
temporarily for the following steps:
Allowing optional string
resultAliasand optional listfieldsin this object."output_local": { "resultAlias":"", "fields":[ "field1", ... ] }}// end `reduce` }// end `QUERY` }// end `expression`
- breakOnMatch
- Optional Boolean value that indicates whether to break out of the
maplist after the current sequence is run. Default value isfalse."breakOnMatch": },
- nestedUpserts
- Optional object to handle the case that needs to generate derived data after multiple line-level
events are looped.
{ "nestedUpserts": {
- nestedPath
- Required string that specifies a nested path with an array. Format is same as the preceding
field path definition.
For example,
a.b.orderLines."nestedPath": “”
- object
- Required object that specifies the fields that you want to get from the initial event.
You can specify the
localIdentifiersfield only in thesendObjectUpsertEvents.map.nestedUpserts.objectlevel."objects": { "localIdentifiers": { "SELECT": "localIdentifier" } }
- map
- Required array that specifies how to process event to get derived data. Definitions for all
fields of
sendObjectUpsertEvents.map.nestedUpserts.mapare the same assendObjectUpsertEvents.map."map": [ {
- if
- Optional object that specifies filter conditions. The definition of operator is same with an
ifevent,"if":{ }} ] // end `sendObjectUpsertEvents.nestedUpserts.map` } // end `nestedUpserts` } // end `sendObjectUpsertEvents.map[1]` ] // end `sendObjectUpsertEvents.map` }// end sendObjectUpsertEvents } end
Example rules
- Update Order.shipmentstatus
-
{ "ruleType": "derived", "name": "shipmentStatus_order_202005221410", "ruleId": "075b876d-b481-47b1-b316-f62fe914594e", "instructions": { "enableCollapse": true, "ifEvent": { "AND": [ { "EQUALS": [ { "SELECT": "eventCode", "type": "STRING" }, { "VALUE": "objectUpsertedEvent", "type": "STRING" } ] }, { "EQUALS": [ { "SELECT": "objectType", "type": "STRING" }, { "VALUE": "Order", "type": "STRING" } ] }, { "EXISTS": [ { "SELECT": "eventDetails.changedFieldPaths.orderLines.shipmentStatus", "type": "STRING" } ] } ] }, "sendObjectUpsertEvents": { "objects": { "id": { "SELECT": "eventDetails.businessObject.id" }, "type": { "SELECT": "eventDetails.businessObject.type" } }, "map": [ { "sequence": 1, "expression": { "QUERY": { "dimension": "orderLines.shipmentStatus", "hint": "orderflow", "reduce": { "expression": { "fieldPath": "orderLines.type", "operator": "COUNT" }, "output_local": { "resultAlias": "lineCountsByShipmentStatus" } } } } }, { "sequence": 2, "output": { "resultFieldPath": "lineCount", "resultType": "int" }, "expression": { "QUERY": { "hint": "orderflow", "reduce": { "expression": { "fieldPath": "orderLines.type", "operator": "COUNT" } } } } }, { "sequence": 3, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "OR": [ { "GREATER_EQUALS": [ { "ADD": [ { "SELECT_LOCAL": "lineCountsByShipmentStatus.OVER_SHIPPED", "TYPE": "INT" }, { "SELECT_LOCAL": "lineCountsByShipmentStatus.FULLY_SHIPPED", "TYPE": "INT" } ] }, { "SELECT_LOCAL": "lineCount", "TYPE": "INT" } ] }, { "GREATER_EQUALS": [ { "SELECT_LOCAL": "lineCountsByShipmentStatus.OVER_SHIPPED", "TYPE": "INT" }, { "SELECT_LOCAL": "lineCount", "TYPE": "INT" } ] } ] }, "expression": { "VALUE": "OVER_SHIPPED", "TYPE": "STRING" } }, { "sequence": 4, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "GREATER_EQUALS": [ { "SELECT_LOCAL": "lineCountsByShipmentStatus.FULLY_SHIPPED", "TYPE": "INT" }, { "SELECT_LOCAL": "lineCount", "TYPE": "INT" } ] }, "expression": { "VALUE": "FULLY_SHIPPED", "TYPE": "STRING" }, "breakOnMatch": true }, { "sequence": 5, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "LESS_THAN": [ { "ADD": [ { "SELECT_LOCAL": "lineCountsByShipmentStatus.OVER_SHIPPED", "TYPE": "INT" }, { "SELECT_LOCAL": "lineCountsByShipmentStatus.FULLY_SHIPPED", "TYPE": "INT" } ] }, { "SELECT_LOCAL": "lineCount", "TYPE": "INT" } ] }, "expression": { "VALUE": "PARTIALLY_SHIPPED", "TYPE": "STRING" } }, { "sequence": 6, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "AND": [ { "EQUALS": [ { "SELECT_LOCAL": "lineCountsByShipmentStatus.FULLY_SHIPPED", "type": "int" }, { "VALUE": 0, "type": "int" } ] }, { "EQUALS": [ { "SELECT_LOCAL": "lineCountsByShipmentStatus.PARTIALLY_SHIPPED", "type": "int" }, { "VALUE": 0, "type": "int" } ] }, { "EQUALS": [ { "SELECT_LOCAL": "lineCountsByShipmentStatus.OVER_SHIPPED", "type": "int" }, { "VALUE": 0, "type": "int" } ] } ] }, "expression": { "VALUE": "NOT_SHIPPED", "TYPE": "STRING" }, "breakOnMatch": true } ] } } }
- Update OrderLine.shipmentstatus
-
{ "ruleType": "derived", "name": "shipmentStatus orderLine", "ruleId": "104bc01e-6752-48bd-bd18-3a05c3d365a6", "instructions": { "enableCollapse": true, "ifEvent": { "AND": [ { "EQUALS": [ { "SELECT": "eventCode", "TYPE": "STRING" }, { "VALUE": "objectUpsertedEvent", "TYPE": "STRING" } ] }, { "EQUALS": [ { "SELECT": "objectType", "TYPE": "STRING" }, { "VALUE": "Order", "TYPE": "STRING" } ] }, { "OR": [ { "EXISTS": [ { "SELECT": "eventDetails.changedFieldPaths.orderLines.shipmentLines.quantity", "TYPE": "FLOAT" } ] }, { "EXISTS": [ { "SELECT": "eventDetails.changedFieldPaths.orderLines.quantity", "TYPE": "FLOAT" } ] } ] } ] }, "sendObjectUpsertEvents": { "objects": { "id": { "SELECT": "eventDetails.businessObject.id" }, "type": { "SELECT": "eventDetails.businessObject.type" } }, "map": [ { "sequence": 1, "nestedUpserts": { "nestedPath": "eventDetails.changedData.orderLines", "objects": { "localIdentifiers": { "SELECT": "localIdentifiers" } }, "map": [ { "sequence": 1, "output": { "resultFieldPath": "shippedQuantity", "resultType": "float" }, "expression": { "QUERY": { "hint": "orderflow", "reduce": { "expression": { "fieldPath": "shipmentLines.quantity", "operator": "SUM" } } } } }, { "sequence": 2, "expression": { "QUERY": { "hint": "orderflow", "output_local": { "fields": [ "quantity" ], "resultAlias": "current_orderLine" } } } }, { "sequence": 3, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "EQUALS": [ { "SELECT_LOCAL": "shippedQuantity", "TYPE": "float" }, { "SELECT_LOCAL": "current_orderLine.quantity", "TYPE": "float" } ] }, "expression": { "VALUE": "FULLY_SHIPPED", "TYPE": "STRING" }, "breakOnMatch": true }, { "sequence": 4, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "GREATER_THAN": [ { "SELECT_LOCAL": "shippedQuantity", "TYPE": "float" }, { "SELECT_LOCAL": "current_orderLine.quantity", "TYPE": "float" } ] }, "expression": { "VALUE": "OVER_SHIPPED", "TYPE": "STRING" }, "breakOnMatch": true }, { "sequence": 5, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "AND": [ { "LESS_THAN": [ { "SELECT_LOCAL": "shippedQuantity", "TYPE": "float" }, { "SELECT_LOCAL": "current_orderLine.quantity", "TYPE": "float" } ] }, { "GREATER_THAN": [ { "SELECT_LOCAL": "shippedQuantity", "TYPE": "float" }, { "VALUE": 0, "TYPE": "float" } ] } ] }, "expression": { "VALUE": "PARTIALLY_SHIPPED", "TYPE": "STRING" }, "breakOnMatch": true }, { "sequence": 6, "output": { "resultFieldPath": "shipmentStatus", "resultType": "string" }, "if": { "EQUALS": [ { "SELECT_LOCAL": "shippedQuantity", "TYPE": "float" }, { "VALUE": 0, "TYPE": "float" } ] }, "expression": { "VALUE": "NOT_SHIPPED", "TYPE": "STRING" }, "breakOnMatch": true } ] } } ] } } }