Unable to filter Array of objects having dynamic keys using dataweave - mule

I want to filter this array of object based on EmployeeStatus which should be only Resigned and Terminated but not active. Here the keys are different for each object and hence I am unable to apply logic like item.key.EmployeeStaus=="Resigned" or "Terminated" .Any suggestions or hint would be helpful for me.
Input Payload
[
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
{
"EmailID": "morganfinely#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196178": [
{
"EmailID": "jenniferjackson#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]
Required Output
[
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
},
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated
}
]

Maybe something like this:
Input
[
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
{
"EmailID": "morganfinely#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196178": [
{
"EmailID": "jenniferjackson#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]
Script
%dw 2.0
output application/json
---
flatten(payload map
($ mapObject {
b: $ filter ($.Employeestatus != "Active")
}).b -[])
Output
[
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
},
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]

Here's another take:
%dw 2.0
output application/json
var data = [
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
{
"EmailID": "morganfinely#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196178": [
{
"EmailID": "jenniferjackson#zylker.com",
"Employeestatus": "Active"
}
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]
---
flatten({(data)} pluck $) filter not ($.Employeestatus == "Active")
I 'll add explanations later on.
EDIT: Here's the explanation and links to the DW documentation:
I make use of the dynamic elements feature {(data)} to destroy the array and collapse all enclosed objects into an object.
I then use pluck to get just the values in an array.
I make use of flatten to collapse the first level of sub-arrays, because the values we just plucked are also arrays. You now have a flat array.
Now I make use of filter to remove eliminate all records that fail the assertion to the right.

You can filter the records by transversing the structure. First an array, using map. Each element is an object with a single key, so let's use mapObject, then filter. I didn't try to remove the empty arrays.
%dw 2.0
output application/json skipNullOn="everywhere"
fun filterEmployeeStatus(e) = e filter ($.Employeestatus == "Resigned" or $.Employeestatus == "Terminated")
---
payload map
( $ mapObject ((value, key, index) -> (key): filterEmployeeStatus(value) ) )
Output:
[
{
"626433000000196190": [
{
"EmailID": "rubyrichards#zylker.com",
"Employeestatus": "Resigned"
}
]
},
{
"626433000000196184": [
]
},
{
"626433000000196178": [
]
},
{
"626433000000196166": [
{
"EmailID": "daveduken#zylker.com",
"Employeestatus": "Terminated"
}
]
}
]

Related

Query item in nested array

Customer appointments with top level locationId sample data set:
[
{
"locationId": 9999,
"customerAppointments": [
{
"customerId": "1",
"appointments": [
{
"appointmentId": "cbbce566-da59-42c2-8845-53976ba63d56",
"locationName": "Sullivan St"
},
{
"appointmentId": "5f09e2af-ddae-47aa-9f7c-fd1001a9c5e6",
"locationName": "Oak St"
}
]
},
{
"customerId": "2",
"appointments": [
{
"appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName": "Kellet St"
}
]
},
{
"customerId": "3",
"appointments": []
}
]
},
{
...
},
{
...
}
]
I need to pull out appointment by locationId and customerId and only get the appointment for that customerId e.g
Sample response:
[
{
"appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName": "Kellet St"
}
]
Tried below query, but it just returns all records for all customers ids (which is kind of expected):
db.getCollection("appointments").find(
{
"locationId" : NumberInt(9999),
"customerAppointments" : {
"$elemMatch" : {
"customerId" : "2"
}
}
}
);
But how can I get just the appointment record for a specific customerId?
When asking this question I was unaware of the older version of MongoDB driver (< v5) so we cannot use the $getField operator.
However, this query seems to work well:
db.getCollection("appointments").aggregate([
{
$match: {
"locationId": NumberInt(9999)
}
},
{
$unwind: "$customerAppointments"
},
{
$match: {
"customerAppointments.customerId": "2"
}
},
{
$project: {
appointments: "$customerAppointments.appointments"
}
}
]);
Yields:
{
"_id" : ObjectId("63eebe95c7a0da54804c1db2"),
"appointments" : [
{
"appointmentId" : "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName" : "Kellet St"
}
]
}

getting lvalue and rvalue of a declaration

Im parsing C++ with ANTLR4 grammar, I have a visitor function for visitDeclarationStatement. In the C++ code that Im trying to parse Person p; or a declaration of any custom type, in the tree I get two similar nodes and I cannot differentiate between the Lvalue and Rvalue!
"declarationStatement": [
{
"blockDeclaration": [
{
"simpleDeclaration": [
{
"declSpecifierSeq": [
{
"declSpecifier": [
{
"typeSpecifier": [
{
"trailingTypeSpecifier": [
{
"simpleTypeSpecifier": [
{
"theTypeName": [
{
"className": [
{
"type": 128,
"text": "Person"
}
]
}
]
}
]
}
]
}
]
}
]
},
{
"declSpecifier": [
{
"typeSpecifier": [
{
"trailingTypeSpecifier": [
{
"simpleTypeSpecifier": [
{
"theTypeName": [
{
"className": [
{
"type": 128,
"text": "p"
}
]
}
]
}
]
}
]
}
]
}
]
}
]
},
{
"type": 124,
"text": ";"
}
]
}
I want to be able to get Variable Type and Variable Name separately. What is the right way of doing that? How can I change the g4 file to get those results in a way that I can differentiate between the type and the name?
Thanks
You don't need to change the grammar. In case of Person p;, which is matched by:
declSpecifierSeq: declSpecifier+ attributeSpecifierSeq?;
the first child of declSpecifierSeq (which is declSpecifier+) will be a List of declSpecifier-contexts, of which the first is the type and the second the name.

MongoError: Expression $in takes exactly 2 arguments. 1 were passed in

below is my query:
while executing below query getting mongoerror : Expression $in takes exactly 2 arguments. 1 were passed in.
i am using $in Comparison operator
{
"$expr": {
"$not": {
"$eq":{
"$and": [
{
"PrName": {
"$in": [
"pname"
]
}
},
{
"AccountId": {
"$in": [
"34562",
"88765",
"87654",
"12345"
]
}
}
]
}
}
}
}
When you use $expr, the operator expressions syntax changes a little:
{ $in: [ <expression>, <array expression> ] }
{
"$expr": {
"$not": {
"$and": [
{
"$in": [
"$PrName",
[
"pname"
]
]
},
{
"$in": [
"$AccountId",
[
"34562",
"88765",
"87654",
"12345"
]
]
}
]
}
}
}

Karate: Match JSON Array responses where the order of array is different in each hit

I have a scenario where a portion of the response arrays is the response from a child API.
child API response looks like below, but there is no specific order. And I need to check whether the child API response is present in the parent API(irrespective of the order of the elements in the child API). I followed this Karate - Match two dynamic responses thread but its not working in my case.
* def response1 =
"""
{
"array1": [
{
"element": {
"id": "A1",
"array11": [
{
"uid": "u123",
"gid": [
"g1"
]
}
]
}
},
{
"element": {
"id": "A2",
"array11": [
{
"uid": "u124",
"gid": [
"g2"
]
}
]
}
}
]
}
"""
* def response2 =
"""
{
"array1": [
{
"element": {
"id": "A2",
"array11": [
{
"uid": "u124",
"gid": [
"g2"
]
}
]
}
},
{
"element": {
"id": "A1",
"array11": [
{
"uid": "u123",
"gid": [
"g1"
]
}
]
}
}
]
}
"""
This is a one liner :)
* match response2.array1 contains response1.array1
Guess what, you don't have to match pure JSON all the time, using child-sections is fine.
But also read this specific part of the docs: https://github.com/intuit/karate#contains-short-cuts
And this example: https://github.com/intuit/karate/blob/master/karate-demo/src/test/java/demo/graphql/graphql.feature

How to implement group by in Dataweave based on first column in CSV

I have an incoming CSV file that looks like this (notice that the first field is common - this is the order number)
36319602,100,12458,HARVEY NORMAN,
36319602,101,12459,HARVEY NORMAN,
36319602,102,12457,HARVEY NORMAN,
36319601,110,12458,HARVEY NORMAN,
36319601,111,12459,HARVEY NORMAN,
36319601,112,12457,HARVEY NORMAN,
36319603,110,12458,HARVEY NORMAN,
36319603,121,12459,HARVEY NORMAN,
36319603,132,12457,HARVEY NORMAN,
This is my current Dataweave code
list_of_orders: {
order: payload map ((payload01 , indexOfPayload01) -> {
order_dtl:
[{
seq_nbr: payload01[1],
route_nbr: payload01[2]
}],
order_hdr: {
ord_nbr: payload01[0],
company: payload01[3],
city: payload01[4],
}
})
}
An example of the desired output would be something like this ... (this is just mocked up). Notice how I would like a single header grouped by the first column which is the order number - but with multiple detail lines
"list_of_orders": {
"order": [
{
"order_dtl": [
{
seq_nbr: 100,
route_nbr: 12458
},
{
seq_nbr: 101,
route_nbr: 12459
},
{
seq_nbr: 102,
route_nbr: 12457
}
],
"order_hdr":
{
ord_nbr: 36319602,
company: HARVEY NORMAN
}
}
]
}
It works fine except that it is repeating the order_hdr key.
What they would like is a single header key with multiple details beneath.
The grouping is to be based on "ord_nbr: payload01[0]"
Any help appreciated
Thanks
I think you're using Dataweave 1. In dw1, this groupBy gets the desired output(Note you can change the field pointers [0],1 etc to field name mappings if you have them set up as metadata etc):
%dw 1.0
%output application/json
---
list_of_orders: {
order: (payload groupBy ($[0])) map {
order_dtl: $ map {
seq_nbr: $[1],
route_nbr: $[2]
},
order_hdr:
{
ord_nbr: $[0][0],
company: $[0][3]
}
}}
UPDATE
Here is the output for the new input sample with multiple orders:
{
"list_of_orders": {
"order": [
{
"order_dtl": [
{
"seq_nbr": "110",
"route_nbr": "12458"
},
{
"seq_nbr": "121",
"route_nbr": "12459"
},
{
"seq_nbr": "132",
"route_nbr": "12457"
}
],
"order_hdr": {
"ord_nbr": "36319603",
"company": "HARVEY NORMAN"
}
},
{
"order_dtl": [
{
"seq_nbr": "100",
"route_nbr": "12458"
},
{
"seq_nbr": "101",
"route_nbr": "12459"
},
{
"seq_nbr": "102",
"route_nbr": "12457"
}
],
"order_hdr": {
"ord_nbr": "36319602",
"company": "HARVEY NORMAN"
}
},
{
"order_dtl": [
{
"seq_nbr": "110",
"route_nbr": "12458"
},
{
"seq_nbr": "111",
"route_nbr": "12459"
},
{
"seq_nbr": "112",
"route_nbr": "12457"
}
],
"order_hdr": {
"ord_nbr": "36319601",
"company": "HARVEY NORMAN"
}
}
]
}
}