Toby Inkster

NAME

RDF::RDB2RDF::Simple - map relational database to RDF easily

SYNOPSIS

 my $mapper = RDF::RDB2RDF->new('Simple', %mappings, -namespaces => \%ns);
 print $mapper->process_turtle($dbh);

DESCRIPTION

This module makes it reasonably easy to dump a relational SQL database as an RDF graph.

Constructor

  • RDF::RDB2RDF::Simple->new(%mappings [, -namespaces=>\%ns])

  • RDF::RDB2RDF->new('Simple', %mappings [, -namespaces=>\%ns])

    The constructor takes a hash of mappings. (See MAPPINGS below.) You may also pass a reference to a set of namespaces. This can be a hashref, or an RDF::Trine::NamespaceMap.

Methods

  • process($dbh [, $destination])

    Given a database handle, produces RDF data. Can optionally be passed a destination for triples: either an existing model to add data to, or a reference to a callback function.

    Returns a RDF::Trine::Model.

  • process_turtle($dbh, %options)

    As per process, but returns a string in Turtle format.

    The mapping is included as a JSON comment at the top of the Turtle. Passing no_json => 1 can disable that feature.

    Returns a string.

  • to_hashref

    Creates a hashref of the mappings and namespaces, which can later be fed back to the constructor to re-produce this object.

    Returns a hashref.

  • to_json(%options)

    Produces the JSON equivalent of to_hashref. Any valid options for the JSON module's to_json function can be passed.

    Returns a string.

  • namespaces

    The namespaces known about by the object.

    Returns a hash.

  • mappings

    The mappings.

    Returns a hashref.

MAPPINGS

It's best just to show you...

 use RDF::Trine::Namespace qw[rdf rdfs owl xsd];
 my $foaf = RDF::Trine::Namespace->new('http://xmlns.com/foaf/0.1/');
 my $bibo = RDF::Trine::Namespace->new('http://purl.org/ontology/bibo/');
 my $dc   = RDF::Trine::Namespace->new('http://purl.org/dc/terms/');
 my $skos = RDF::Trine::Namespace->new('http://www.w3.org/2004/02/skos/core#');

 my %simple_mapping = (
 
   -namespaces => {
     bibo  => "$bibo",
     dc    => "$dc",
     foaf  => "$foaf",
     rdfs  => "$rdfs",
     skos  => "$skos",
     },
 
   books => {
     about     => 'http://example.net/id/book/{book_id}',
     typeof    => [$bibo->Book],
     columns   => {
       title    => [{property => $rdfs->label, lang=>'en'},
                    {property => $dc->title, lang=>'en'}],
       turtle   => [{parse => 'Turtle'}],
       },
     },
 
   authors => {
     select    => "*, forename||' '||surname AS fullname",
     about     => 'http://example.net/id/author/{author_id}',
     typeof    => [$foaf->Person],
     columns   => {
       forename => [{property => $foaf->givenName}],
       surname  => [{property => $foaf->familyName}],
       fullname => [{property => $rdfs->label},
                    {property => $foaf->name}],
       turtle   => [{parse => 'Turtle'}],
       },
     },
 
   topics => {
     about     => 'http://example.net/id/topic/{topic_id}',
     typeof    => [$skos->Concept],
     columns   => {
       label    => [{property => $rdfs->label, lang=>'en'},
                    {property => $skos->prefLabel, lang=>'en'}],
       turtle   => [{parse => 'Turtle'}],
       },
     },
 
   book_authors => {
     about     => 'http://example.net/id/book/{book_id}',
     columns   => {
       author_id=> [{rel => $dc->creator,
                     resource => 'http://example.net/id/author/{author_id}'},
                    {rel => $foaf->maker,
                     resource => 'http://example.net/id/author/{author_id}'},
                    {rev => $foaf->made,
                     resource => 'http://example.net/id/author/{author_id}'},
                    {rel => $bibo->author,
                     resource => 'http://example.net/id/author/{author_id}'}],
       },
     },
 
   book_topics => {
     about     => ['http://example.net/id/book/{book_id}'],
     columns   => {
       topic_id => [{rel => $dc->subject,
                     resource => 'http://example.net/id/topic/{topic_id}'}],
       },
     },
   );
        

Looking at the "books" mapping alone for now, we see:

     about     => 'http://example.net/id/book/{book_id}',

This tells us that for each row of the "books" table in the database, generate a subject URI using the template http://example.net/id/book/{book_id}. Note that column names appearing in curly braces get substituted for the relevent values.

Generating blank nodes is easy: either use a template along the lines of _:book{book_id} or simply omit the "about" line altogether.

     typeof    => [$bibo->Book],

This is a shorthand for assigning classes to the subject URI.

     columns   => {
       title    => [{property => $rdfs->label, lang=>'en'},
                    {property => $dc->title, lang=>'en'}],

This says to map the "title" column of the table to rdfs:label and dc:title. These will be literals, with language tag "en".

       turtle   => [{parse => 'Turtle'}],
       },

This last bit is somewhat weird and experimental. If you have a varchar/text column in your database that includes chunks of Turtle, these can be parsed into the model too. They are parsed using the current namespace map, with a base URI corresponding to the URI from "about".

In addition to the "about", "typeof" and "columns" options there are also "select" and "from" options allowing you to fine tune exactly what data the mapping is processing. And indeed, there is an "sql" option which overrides both. An example of "select" is shown in the authors mapping above.

Note that within:

  {property => $dc->title, lang=>'en'}

there is a whole lot of interesting stuff going on. The object of the triple here is a literal. If it were a URI, we'd do this:

  {rel => $dc->title}

Note that these correspond with the meanings of "property" and "rel" in RDFa. Like RDFa, there is also "rev" which reverses the subject and object of the triple. An example can be seen in the "book_authors" mapping above for foaf:made.

For literals "lang" and "datatype" further qualify them.

Usually, the contents of the database field are used. For example:

     columns   => {
            book_id   => [{ property => $dc->identifier }],
       },

However, sometimes you might want to slot the data from the database into a template:

     columns   => {
            book_id   => [{ property => $dc->identifier,
                                 content  => 'urn:example:book:{book_id}' }],
       },

In these cases, the column mapping key becomes pretty irrelevent. The following will still work fine on the same database:

     columns   => {
            foobar    => [{ property => $dc->identifier,
                                 content  => 'urn:example:book:{book_id}' }],
       },

When "rel" or "rev" are used (i.e. not "property"), then "resource" should be used (i.e. not "content").

Pretty much anywhere where a URI or literal value is expected, you can either give a string, or an RDF::Trine::Node. In cases of strngs, they will be interpolated as templates. RDF::Trine::Nodes are not interpolated.

BUGS

Please report any bugs to http://rt.cpan.org/Dist/Display.html?Queue=RDF-RDB2RDF.

SEE ALSO

RDF::Trine, RDF::RDB2RDF, RDF::RDB2RDF::R2RML.

http://www.perlrdf.org/.

AUTHOR

Toby Inkster <tobyink@cpan.org>.

COPYRIGHT

Copyright 2011-2013 Toby Inkster

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

DISCLAIMER OF WARRANTIES

THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.