In this tutorial, the ontology is already provided. We will focus on the mapping and the lenses. Our goal is to reproduce a fragment of the following diagram (the rest will be given as an exercice).
- Go to your instance of Ontopic Studio.
- Create a project
dest-USERNAME
by replacingUSERNAME
by your user name and using the sample DB. - Open the project
- Go to the
Lenses
page. You see there, on the left, the list of database tables and views.
- Go to the
Ontology
page - Download and unzip the archive containing the ontology files (available in the
ontologies
directory). - Import the file
schema.owl
- Import the file
geosparql.owl
- Go to the
Lenses
page - Among the
Source Tables
(on the left), select the schemasource1
to filter the tables - Select the table
source1.hospitality
and click onGenerate mirror lens
- Click on
lenses.source1.hospitality
on the right to open the newly created lens. - Click on
Constraints
and observe that a unique constraint is defined on theh_id
column, as well as foreign key on them_id
column. - The column
geometrypoint
is in a binary format and needs to be converted into the Well-Known Text format. Click on the menu of the columngeometrypoint
and click onEdit
. - At the bottom, select the transformation
Geo To Well-Known Text
and click on the button+
. Click onPreview
to preview the results. Then, click onUpdate column
.
- Go to the
Mapping
page and click on the lenslenses.source1.hospitality
. - Let's map all the rows to a class. Click on the button
C+
for creating a mapping entry. - We need first to specify the subject as a template. Make sure the option
Template
is selected. Open the template menu and click onCreate new template
. Ontopic Studio automatically proposes the templatedata:source1-hospitality/{h_id}
out of the lens name and the unique constraint on the columnh_id
. Accept it by clicking onCreate
. - Let's now assign a class. Make sure
Constant
is selected for the class. In the drop-down menu below select the classschema:LodgingBusiness
. Click and save and you are having your first mapping entry!
- Let's now map the name in English to the lodging business. Let's create a property mapping entry for the same subject by clicking on the button
P+
on the right of the IRI templatedata:source1-hospitality/{h_id}
. - You should see that subject section is already filled with the same values as before. If it is not the case, you probably clicked on the other
P+
button at the top of the page. In that case, go back and click on the correctP+
button. - Select the property
schema:name
in the property drop-down menu. - For the object, we want to direct map the value from the column
name_en
. SelectLiteral
and the typeColumn
and then thename_en
in the column drop-down menu. - Notice that the datatype field get automatically filled after selecting the column as
xsd:string
. This is because the column type istext
and, according to R2RML character string types are mapped to that RDF datatype. However here we want to assign a language tag (en), so as to distinguish from the names in German and Italian. Select the value@en
in the Datatype/Language drop-down menu and save the mapping entry.
- Let's now map the default geometry of the lodging business. As previously, click on the button
P+
on the right of the IRI templatedata:source1-hospitality/{h_id}
. - Select the property
geo:defaultGeometry
. - For object, you can see that the pre-selected kind value is not
Literal
as before butIRI/BNode
. This is because the propertygeo:defaultGeometry
is declared in the ontology as an object property, so it expects an IRI or a BNode as value. The typeTemplate
is also pre-selected because it is the most common mechanism for building an IRI as object. Let's keep it. - We need to provide an IRI template for geometry objects. Here we have no plan to share the same geometries between lodging businesses, so let's create one geometry object per lodging business, using the unique constraint of the lens (
h_id
). In the template drop-down menu, click onCreate new template
. This time we need to modify the default value suggested by the platform. Replace the text entrydata:source1-hospitality/
bydata:geo/source1-hospitality/
and click onCreate
. Save the mapping entry.
- Let's now map the geometry value to the new IRI template. Since the subject is not the same as in the previous mapping entries, click on the
P+
button at the top the page. - For the subject, select the template
data:geo/source1-hospitality/{h_id}
. - For the property, select
geo:asWKT
. - For the object, keep
Literal
as kind and select the columngeometrypoint
. For its datatype, selectgeo:wktLiteral
. Save the mapping entry.
- We now want to map to sub-classes of
schema:LodgingBusiness
depending on the values found in the columnh_type
. Let's create a new mapping entry. Click onC+
on the right of the templatedata:source1-hospitality/{h_id}
. - For the class, we don't want to assign the same value to each lodging business found in the lens, so we cannot select the type
Constant
. Select instead the typeDictionary
. - For the column, select
h_type
. - Let's now fill the first line of the dictionary. On the left field, insert the string
Camping
as found in theh_type
column of the lens. In the right field, select the classschema:Campground
. Everytime the valueCamping
is found in the columnh_type
, the lodging business will be declared instance of the classschema:Campground
. - Click on
+
for adding a new line. Map this time the valueHotelPension
to the classschema:Hotel
. - Map the value
BedBreakfast
toschema:BedAndBreakfast
. Save the mapping entry.
We have produced enough mapping entries for this lens for the moment. We leave the rest as a homework exercise. Please refer to the VKG diagram to see which properties are missing.
- Go on the
Dashboard
page and click onSnapshot
. Technically speaking, it will create a Git commit with all the important files of the project. - Open the
Repository
page to see the following snapshotted/committed files:lenses.json
: definition of the lenses in the Ontop format.mapping.ttl
: R2RML mapping file defined over the lenses.ontology.ttl
: RDFS/OWL2QL ontology serialized in Turtle.YOUR_PROJECT.ontopicprj
: internal representation of your project. Can be imported in Ontopic Studio to override the mapping, lenses and the ontology.
- Go back to the Ontopic Studio tab. Go the
Mapping page
. Click onExport mapping
and then onWithout lenses
to download the mapping in R2RML that directly refers to tables in the source instead of the lenses. This file is interoperable with any R2RML processor.
Let's test our mapping by deploying Ontop directly in Ontopic Studio and issue our first SPARQL query.
- Go to the
Query
page. Click onStart
at the top right. - Execute the following SPARQL query:
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX schema: <http://schema.org/>
SELECT * WHERE {
?h a schema:Campground ; schema:name ?name .
FILTER (lang(?name) = 'en')
OPTIONAL {
?h geo:defaultGeometry / geo:asWKT ?geometry .
}
}
- Click on
View SQL
to see the generated SQL query.
- Go to the
Lenses
page and create a mirror lens for the tablesource2.hotels
. Open the newly created lens. - We can see it has similar kind of information but with a different column names and special values. Let's keep the lens as it is for the moment and start mapping it. For that, click at bottom right on
0 mapping entries
to reach the mapping editing page for this lens. - Create a class mapping entry with a new IRI template to map all the rows of the lens to the class
schema:LodgingBusiness
. - Map the name in English of the lodging businesses.
- Map the following values of the column
htype
:- 1 to
schema:BedAndBreakfast
- 2 to
schema:Hotel
- 4 to
schema:Campground
.
- 1 to
- Snapshot the changes.
- Go to the
Query
page and update the SPARQL endpoint. - Run the previous SPARQL and observe that it now returns more results. If you look at SQL query, you will see that is now contains a UNION.
- Create a mirror lens from the table
source1.municipalities
. Open the newly created lens. - Click on
Constraints
and observe that this lens contains 2 unique constraints: one onm_id
, one onistat
. The first column is an internal identifier that is specific tosource1
. The second column is the official code of the municipality assigned by the Italian Institute of Statistics (Istat). - Go to the page about the lens
lenses.source1.hospitality
and notice it has a columnm_id
referring to the internal code of the municipality. - Go to the page about the lens
lenses.source2.hotels
and observe it has a columnmun
referring to the Istat code. - As we would to use the same municipality identifiers for the lodging businesses from the 2 sources, let's use the Istat code for in the IRI template of municipalities and not the internal one.
- Go to the mapping page of the lens
lenses.source1.municipalities
. Click onC+
for creating a class mapping entry. - Click on
Create IRI template
. By default Ontopic Studio generates a template using the first unique constraint (m_id
). Replace the binding valuem_id
byistat
. Create the template. - schema.org does have the class for municipalities so let's create one. In the class drop-down menu, click on
Create new class
. InsertMunicipality
as class name and selectschema:AdministrativeArea
as parent. Click onCreate
. Save the mapping entry. - Map the English name of the municipality.
- Snapshot the changes.
- Go to the
Dashboard
page. Click onManage project prefixes
. - Change the value associated to
voc
tohttp://tutorial.example.org/voc#
. Click onSave
and replyYes
to the question. We now changed the IRI ofvoc:Municipality
. - Snapshot the changes.
For creating a mapping entry linking lodging businesses from source 1 to their municipality, we need to obtain their local identifier columns (respectively h_id
and istat
) in the same lens. The lenses lenses.source1.hospitality
and lenses.source1.municipalities
only contain one of the two. Therefore we need to create a join lens to obtain the two columns at the same time.
- Go the
Lenses
page. On the left, select the tablessource1.hospitality
andsource1.municipalities
and click onCreate join lens
. Insert the namesource1.hospitality-municipalities-join
. - For
source1.hospitality
, provide the prefixh_
and forsource1.municipalities
the prefixm_
. All the columns coming from the first table will prefixed byh_
while the ones from the second table bym_
. - Add an equality between
h_m_id
andm_m_id
. Click onCreate join lens
. - Open
lenses.source1.hospitality-municipalities-join
and click on0 mapping entries
. - Click on
P+
to create a property mapping entry. - Select
data:source1-hospitality/{h_id}
as template for the subject. For the binding of the placeholderh_id
in the template, select the columnh_h_id
(it could not be pre-selected because there is no columnh_id
in this lens). - Select the property
schema:containedInPlace
. - Select
IRI/BNode
for the object,data:source1-municipalities/{istat}
as template and the columnm_istat
as binding for the placeholderistat
. Save the mapping entry.
- Go the mapping page of the lens
lenses.source2.hotels
. - Observe that the
mun
column has an integer datatype. However inlenses.source1.municipalities
, theistat
column is a string and starts with the character0
. So here we have to be careful in creating IRIs for the municipalities that match the ones oflenses.source1.municipalities
. - Click on
P+
on the right ofdata:source2-hotels/{id}
. Select the propertyschema:containedInPlace
. - Select
IRI/BNode
for the object. Create a new IRI templatedata:source1-municipalities/0{mun}
and select it. Save the mapping entry. - Snapshot the changes.
- Update the SPARQL endpoint and run the following query:
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX schema: <http://schema.org/>
PREFIX voc: <http://tutorial.example.org/voc#>
SELECT * WHERE {
?h a schema:Campground ; schema:name ?name ; schema:containedInPlace ?municipality .
?municipality a voc:Municipality ; schema:name ?municipalityName .
FILTER (lang(?name) = 'en' && lang(?municipalityName) = 'en')
OPTIONAL {
?h geo:defaultGeometry / geo:asWKT ?geometry .
}
}
Let's enrich the ontology by defining schema:containedInPlace
as inversed property of schema:containsPlace
.
- Go to the
Ontology
page. In theProperties
tab, select the propertyschema:containedInPlace
. Since schema.org is not an OWL ontology, it does not classify its properties as data or object properties. SelectObject
as type for this property. - A new button appears:
Inverse Property
. Click on it and selectschema:containsPlace
as inverse property. Click onSave
. - Go to the property
schema:containsPlace
. Declare it as an object property. - Snapshot the changes.
- Try the following SPARQL query:
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX schema: <http://schema.org/>
PREFIX voc: <http://tutorial.example.org/voc#>
SELECT * WHERE {
?h a schema:Campground ; schema:name ?name .
?municipality a voc:Municipality ; schema:name ?municipalityName ; schema:containsPlace ?h .
FILTER (lang(?name) = 'en' && lang(?municipalityName) = 'en')
OPTIONAL {
?h geo:defaultGeometry / geo:asWKT ?geometry .
}
}
- Notice it returns the same results as before, thanks to the Ontop inference capabilities.
- Go the
Search
page. You can see on the right all the mapping entries created. - On the left, select the class
schema:LodgingBusiness
. You now see only entries where the subject is instance ofschema:LodgingBusiness
. - On the
Templates
tab, select the templatedata:source2-hotels/{id}
. Results are further filtered and only mapping entries fromlenses.source2.hotels
. - Unselect the class
schema:LodgingBusiness
and observe that the mapping entries for the subclassesschema:Hotel
etc. reappear.