I was able to experiment a little with including JSONB in R2RML triples map queries .. and it worked .. which isn't surprising.
Some really simple examples below, in case they are of interest.
The good news .. it works.
The less-good news .. it's inherently difficult to wrangle deep tree-structured objects this way. In the end, the query needs to produce records that are essentially rows with uniformly typed columns.
In any case, the first simple example was a triple for a type called "MeasureParameter" looked like this:
:Item{id} a :MeasureParameter ; :units {units} ; :value {value} ; :paramType {paramType} .
And the corresponding SQL query looked like this:
SELECT *
from (
Select
id,
cast (content ->> 'units' as varchar) as units,
cast (content ->> 'value' as float) as value,
cast (content ->> 'paramType' as varchar) as paramType
FROM public."LibraryItem"
where
type = 'Parameter'
) as MeasureParameters
where units is not null
So, basically, fields named units
, type
, and paramType
were hauled out of a JSONB block and converted into column values,
Interestingly, the query would not work in postgres w/o the little where units is not null
clause .. which was ok, because it's a type guard that distinguishes 'MeasureParameter' records from other kinds of parmeter records.
I tested this using the following simple SPARQL query for 'MeasureParameter' records worked as expected.
PREFIX : <http://resilience.com/stellarforge#>
SELECT ?s ?units ?value ?paramType WHERE {
?s rdf:type :MeasureParameter;
:units ?units;
:value ?value;
:paramType ?paramType.
}
One quirk was that I had to enable Ontop's data inference capabilities: ontop.inferDefaultDatatype=true
.. so using non-standard ways to generate SQL rows (in this case, JSONB operations) seems like it raises some risk of introducing minor quirks.
FWIW, here is an example of using the postgres jsonb_array_elements
function to "expand" each record in a table by creating a row for each item in a contained JSONB array. In this example, the "LibraryItem"
table has a JSONB column named content
, and that content
's value, in many cases, includes an items
field, The items
field is an array of structures, and those structures have a name
, type
, and instanceId
field (and several other field besides .. it's a deep tree structure).
In any case, the following query:
SELECT
id,
(items ->> 'name')::text AS name,
(items ->> 'type')::text AS type,
(items ->> 'instanceId')::text AS instanceId
FROM
public."LibraryItem",
jsonb_array_elements(content->'items') as items
Produces a result like this:
id |
name |
type |
instanceid |
0284f6ae-9a51-40aa-bd6d-9551a56d4d70 |
Load |
Element |
7637713a-995f-4c1c-b30b-c19e476de8d9 |
0284f6ae-9a51-40aa-bd6d-9551a56d4d70 |
Wash |
Element |
0d2073e8-2f22-4887-9e13-b90697c6091e |
0284f6ae-9a51-40aa-bd6d-9551a56d4d70 |
Elute |
Element |
91acc736-52b7-4014-9170-b6ebbbbea6fe |
8e3ec7de-1e99-4aef-9a85-2bb18d3be211 |
Temperature |
Parameter |
b0558eb5-0171-4482-b4c0-6d01df84846a |
8e3ec7de-1e99-4aef-9a85-2bb18d3be211 |
SpecificFuelConsumption |
Parameter |
f9c63e0d-3f8c-492d-b245-8f0d62ac1e1a |
8e3ec7de-1e99-4aef-9a85-2bb18d3be211 |
RotationalSpeed |
Parameter |
e1dabe66-1446-441d-906f-16cf24201245 |
8e3ec7de-1e99-4aef-9a85-2bb18d3be211 |
RotationalSpeed |
Parameter |
8fef1191-9f5b-4eac-9c7e-577c5b8e19dc |
f5b66049-7519-418d-97f3-e8eba599da02 |
AddLiquid |
Element |
3f58b9dc-628f-4732-be6b-dab8166ff824 |