If I run SMS on a CSV, the order of bindings is pretty obvious - every row of the CSV is fed into the WHERE
section, and the resulting bindings are then used to build the triples in the TO
section. In this case, if do a BIND(UUID() as ?row)
and then assert ?row a :Row
, I should expect one triple for each row in the CSV
However, If I have a nested JSON data structure with arrays of varying sizes, e.g.
{
"elements": [
{
"eid": 1,
"props": {
"A": [
{
"pid": "1-A1"
},
{
"pid": "1-A2"
}
],
"B": [
{
"pid": "1-B1"
},
{
"pid": "1-B2"
},
{
"pid": "1-B3"
}
]
}
}
]
}
which I then map with
MAPPING :json_test
FROM JSON {
{
"elements": [
{
"eid": "?eid",
"props": {
"A": [
{
"pid": "?prop_a_id"
}
],
"B": [
{
"pid": "?prop_b_id"
}
]
}
}
]
}
}
TO {
?input_set :bindings ?bindings
}
WHERE {
bind(uuid() as ?input_set)
BIND(CONCAT(STR(?eid),'-',
COALESCE(?prop_a_id, 'NO_A'),'-',
COALESCE(?prop_b_id, 'NO_B')
) as ?bindings)
}
would it result in a DFS traversal of the JSON structure with an input set emitted into the WHERE/TO at each leaf, i.e. I should expect 5 UUIDs bound with the inputs being
{eid:1,a_prop_id:"1-A1"}
{eid:1,a_prop_id:"1-A2"}
{eid:1,b_prop_id:"1-B1"}
{eid:1,b_prop_id:"1-B2"}
{eid:1,b_prop_id:"1-B3"}
because what I am seeing is quite different - I am seeing a single UUID bound to a cross product (6 values) of As and Bs. It gets even more interesting if not all values are populated - if the B array is empty, for example, I will get 2 bindings, one with each A value + '-NO_B', but if the 'B' element is removed entirely, I get no bindings, even though A values are there. Is there a way to make a sub-tree as optional?