RMLio / rmlmapper-java

The RMLMapper executes RML rules to generate high quality Linked Data from multiple originally (semi-)structured data sources
http://rml.io
MIT License
151 stars 61 forks source link

JSON parent/child mapping #230

Closed namedgraph closed 9 months ago

namedgraph commented 9 months ago

Hi,

I'm scratching my head about a seemingly simple use case of mapping

[
  { "id": "parent_1", "children": [ "child_1A", "child_1B" ] },
  { "id": "parent_2", "children": [ "child_2A" ] }
]

to

ex:parent_1 ex:child ex:child_1A, ex:child_1B .
ex:parent_2 ex:child ex:child_2A .

I know a mapping condition needs to be used here, but I don't understand how to formulate it. This is my attempt:

prefixes:
  ex: http://example.org/

sources:
  parents:
    access: data.json
    referenceFormulation: jsonpath
    iterator: "$[*]"
  children:
    access: data.json
    referenceFormulation: jsonpath
    iterator: "$[*].children[*]"
mappings:
  Parent:
    sources: parents
    s: ex:$(id)
    po:
      - [ ex:label, $(id) ]
      - p: ex:child
        o:
          - mapping: Child
            condition:
              function: equal
              parameters:
                - [ str1, "$.children[*]", s ]
                - [ str2, $(@), o ]
  Child:
    sources: children
    s: ex:$(@)
    po:
      - [ ex:label, $(@) ]

but it does not produce any mappings:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ex: <http://example.org/> .

ex:parent_1 ex:label "parent_1" .

ex:parent_2 ex:label "parent_2" .

ex:child_1A ex:label "child_1A" .

ex:child_1B ex:label "child_1B" .

ex:child_2A ex:label "child_2A" .

If I remove the condition altogether then I get a cartesian product:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ex: <http://example.org/> .

ex:parent_1 ex:label "parent_1" ;
    ex:child ex:child_1A, ex:child_1B, ex:child_2A .

ex:parent_2 ex:label "parent_2" ;
    ex:child ex:child_1A, ex:child_1B, ex:child_2A .

ex:child_1A ex:label "child_1A" .

ex:child_1B ex:label "child_1B" .

ex:child_2A ex:label "child_2A" .

It looks like a similar issue to https://github.com/semantifyit/RocketRML/issues/17 but their solution uses a non-standard ^^ JSONPath operator.

namedgraph commented 9 months ago

@bjdmeest can you help? :)

bjdmeest commented 9 months ago

In this case, since you directly use identifiers within nested documents, there's no need for a condition and you could just do as below

prefixes:
  ex: http://example.org/

sources:
  parents:
    access: data.json
    referenceFormulation: jsonpath
    iterator: "$[*]"
  children:
    access: data.json
    referenceFormulation: jsonpath
    iterator: "$[*].children[*]"
mappings:
  Parent:
    sources: parents
    s: ex:$(id)
    po:
      - [ ex:label, $(id) ]
      - [ ex:child, "ex:$(children[*])~iri" ]
  Child:
    sources: children
    s: ex:$(@)
    po:
      - [ ex:label, $(@) ]
namedgraph commented 9 months ago

Thanks, it works. Just not as explicit as the mapping form.