I want to create a JQ function that allows me to
to filter an array in the JSON tree, based on parent's / sibling properties;
1 - I want to wrap function but i can't due to the scope of parent;
2 - I want to invoke that function but with other properties;
Some dummy Data:
[
{
"storeId": "s2",
"storehouseInfo": {
"id": "025453",
"name": "00211 NW, OR",
"maxPallets": 10
},
"workorder":{
"id": "w2s2",
"startDate": "2019-09-06T10:00:00.000Z",
"vendorId":"v2"
},
"events": [
{
"id": "e4",
"storeId": "s2",
"vendorId": "v1",
"startDate": "2019-09-05T10:00:00.000Z",
"endDate": "2019-09-14T00:00:00.000Z",
"palletsUsed": 5
},
{
"id": "e5",
"storeId": "s2",
"vendorId": "v2",
"startDate": "2019-09-05T00:00:00.000Z",
"endDate": "2019-09-14T00:00:00.000Z",
"palletsUsed": 5
},
{
"id": "e10",
"storeId": "s2",
"vendorId": "v1",
"startDate": "2019-09-06T10:00:00.000Z",
"endDate": "2019-09-14T00:00:00.000Z",
"palletsUsed": 5
},
{
"id": "e11",
"storeId": "s2",
"vendorId": "v2",
"startDate": "2019-09-06T00:00:00.000Z",
"endDate": "2019-09-14T00:00:00.000Z",
"palletsUsed": 5
},
{
"id": "e12",
"storeId": "s2",
"vendorId": "v2",
"startDate": "2019-09-06T10:00:00.000Z",
"endDate": "2019-09-14T00:00:00.000Z",
"palletsUsed": 5
}
]
},
]
Current working function:
. | map( . as $parent |
.
+
{
"conflictsInPeriod":
[.events[] | (
getFieldsThatCheckConditionInArray(
# conditions
(
( ($parent.workorder.startDate | dateDaysAgo(12*7) ) < .endDate)
and
(.vendorId == $parent.workorder.vendorId)
);
# props we want to return
{
event:.id,
wo_sd: $parent.workorder.startDate[:10],
workorder_id: $parent.workorder.id
})
)]
}
)
Some aux functions:
def generateConflictArray(arrayName;arrayToCheck;conflictToCheck):
map( . +
{
(arrayName): [arrayToCheck | (conflictToCheck)]
}
);
def getFieldsThatCheckConditionInArray(condition;returnValues) :
if (condition) then (returnValues) else empty end;
Desired Function CALL:
. | generateConflictArray(
"conflictsInPeriod";
.events[];
getFieldsThatCheckConditionInArray(
# conditions
(
( ($parent.workorder.startDate | dateDaysAgo(12*7) ) < .endDate)
and
(.vendorId == $parent.workorder.vendorId)
);
# props we want to return
{
event:.id,
event_endDate:.endDate,
wo_sd: $parent.workorder.startDate[:10],
workorder_id: $parent.workorder.id
})
)
Desired Output (All the array data, + newly created array " "conflictsInPeriod"", inside each element of the array):
[
{
"conflictsInPeriod":[
{
"event": "e5",
"workorder_sd": "2019-09-06",
"workorder_id": "w2s2"
},
{
"event_id": "e11",
"workorder_sd": "2019-09-06",
"workorder_id": "w2s2"
},
{
"event_id": "e12",
"workorder_sd": "2019-09-06",
"workorder_id": "w2s2"
}
]
}
]
...
解决方案
Maybe this is closer to what you're looking for:
def etl(keyname; arrayname; cond; result):
def etl:
. as $parent
| .[arrayname][]
| { parent: $parent, child: .}
| select(cond) | result;
{(keyname): map(etl)}
;
## Invocation:
etl("conflictsInPeriod";
"events";
( (.parent.workorder.startDate | dateDaysAgo(12*7) ) < .child.endDate)
and
(.child.vendorId == .parent.workorder.vendorId);
{
event: .child.id,
wo_sd: .parent.workorder.startDate[:10],
workorder_id: .parent.workorder.id
}
)
Notice how the conditions are written in relation to .parent and .child rather than $parent and ..