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
146 stars 61 forks source link

Many to many mapping using Json #164

Closed JoshWoodArup closed 2 years ago

JoshWoodArup commented 2 years ago

I have the following data:

{
    "Parents": [
        {
            "Name": "John"
        },
        {
            "Name": "Jane"
        }
    ],
    "Children": [
        {
            "Name": "Jack"
        },
        {
            "Name": "Jill"
        }
    ]
}

John and Jane are both parents of Jack and Jill, and I'd like to create a many to many relationship showing this. I tried the following set of rules, hoping that having an array in the subject map would generate multiple subjects, but it only produced the first.

@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix mapping: <http://example.org/mapping/> .
@prefix : <http://example.org/rules/> .

:ParentLinkMap a rr:TriplesMap;
  rml:logicalSource [
    rml:source "data.json";
    rml:referenceFormulation ql:JSONPath;
    rml:iterator "$"
  ].

:ParentLinkMap rr:subjectMap [
  rr:template "mapping:{Parents[*].Name}";
  rr:class mapping:parent;
].

:ParentLinkMap rr:predicateObjectMap [
  rr:predicate mapping:hasChild;
  rr:objectMap [
    rr:template "mapping:{Children[*].Name}";
  ];
].

Is there a way to do this?

Expected output:

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

<mapping:John> a mapping:parent;
  mapping:hasChild <mapping:Jack>, <mapping:Jill> .

<mapping:Jane> a mapping:parent;
  mapping:hasChild <mapping:Jack>, <mapping:Jill> .

Actual output:

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

<mapping:John> a mapping:parent;
  mapping:hasChild <mapping:Jack>, <mapping:Jill> .
DylanVanAssche commented 2 years ago

You can do this through a join of 2 Triples Maps:

@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix mapping: <http://example.org/mapping/> .
@prefix : <http://example.org/rules/> .

:ParentLinkMap a rr:TriplesMap;
  rml:logicalSource [
    rml:source "data.json";
    rml:referenceFormulation ql:JSONPath;
    rml:iterator "$.Parents[*]"
  ].

:ParentLinkMap rr:subjectMap [
  rr:template "mapping:{Name}";
  rr:class mapping:parent;
].

:ParentLinkMap rr:predicateObjectMap [
  rr:predicate mapping:hasChild;
  rr:objectMap [
    a rr:RefObjectMap ;
    rr:parentTriplesMap :ChildrenMap;
  ];
].

:ChildrenMap a rr:TriplesMap;
  rml:logicalSource [
    rml:source "data.json";
    rml:referenceFormulation ql:JSONPath;
    rml:iterator "$.Children[*]"
  ].

:ChildrenMap rr:subjectMap [
  rr:template "mapping:{Name}";
  rr:class mapping:parent;
].

Result:

<mapping:John> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/mapping/parent>.
<mapping:John> <http://example.org/mapping/hasChild> <mapping:Jack>.
<mapping:John> <http://example.org/mapping/hasChild> <mapping:Jill>.
<mapping:Jane> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/mapping/parent>.
<mapping:Jane> <http://example.org/mapping/hasChild> <mapping:Jack>.
<mapping:Jane> <http://example.org/mapping/hasChild> <mapping:Jill>.
<mapping:Jack> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/mapping/parent>.
<mapping:Jill> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/mapping/parent>.

Feel free to contact us again if you still have questions :)