-
Notifications
You must be signed in to change notification settings - Fork 0
HandlingNArityTutorial
Up until now, we have dealt only with binary relations. However, in many cases relations are not binary, but n-ary (i.e., they involve several components). For example, consider the product prices distribution in a marketplace business database. The relationship takes three entities: a supermarket, a product and a price such that the supermarket and product determine the price of a product. Formally, we defined it as:
hasOfferedPrice(?Supermarket, ?Product, ?Price)N-ary relations are natural in the world, however, OWL and RDF only allow for binary relations. Any n-ary relation must be reconstructed by means of a technique known as reification, that is, dealing with the n-ary tuple as if it was an entity, and connecting each component of the tuple to this entity by means of binary relations. For the example above, a reified version would introduce the reified relation Offer that bridges all the entities. Given this new entity we can model a tuple in the previous n-relationship as three binary tuples:
hasOffer(?Supermarket, ?Offer) hasProduct(?Offer, ?Product) hasPrice(?Offer, ?Price)This is a common practice in OWL and RDF, and is also possible in -ontop- mappings. We will now see how to do it through a simple example.
As usual, before we start, make sure you have the tutorial database, in this case the StudentEnrollment database. The StudentEnrollment database consists of 3 tables with a many-to-many relation. Download enrollment.sql. If you have not installed it, see Installing the Tutorial Databases and return here when you've completed the installation.
The usual case for having n-ary relationship (n>2) is when a table introduces a compound key. That is, when some components determine the value of others. For example, in the case of this example Student + Course + Semester determine the Score value (see the figure below).
In this particular case we will reify the enrollment relation as a new class called **: Enrollment**, where an individual of this class represents a tuple of the n-ary enrollment relation. Each Enrollment instance will be associated to one instance of Student, Course and Semester and to one value for the grade. To do this association we will use the object properties :applies, :hasCourse, and :hasSemester, respectively. Once the mappings are in place each tuple of the n-ary relationship will spawn a "virtual graph" composed by only binary relations, for example, the first row of the enrollment table will generate the following graph:
The mapping that will generate the Enrollment instances is as follows:
select co_code, st_code, sm_code, gr_score from grade | → | :enrollment/{sm_code}/{co_code}/{st_code}/ a <font color="#ff0000">:Enrollment</font> ; <font color="#4AA02C">:score</font> <font color="#E9AB17">{gr_score} </font>. |
Notice that we use all the components of the compound key to create the URI for the individual, that is, co_code, st_code and sm_cod. We will now connect this URI to each of the components of the n-ary relation by mapping the appropriate object properties.
select co_code, st_code, sm_code from grade | → | :student-{st_code} <font color="#1569C7">:applies </font> :enrollment/{sm_code}/{co_code}/{st_code}/ . |
select co_code, st_code, sm_code from grade | → | :enrollment/{sm_code}/{co_code}/{st_code}/ <font color="#1569C7">:hasCourse </font>:course-{co_code} . |
select co_code, st_code, sm_code from grade | → | :enrollment/{sm_code}/{co_code}/{st_code}/<font color="#1569C7">:hasSemester </font> :semester-{sm_code} . |
The mappings for the Student, Course and Semester class, as well as the studentName, studentID, courseName, etc., are defined as in the previous tutorials.
With these mappings in place we can now query the n-ary relation by specifying appropriate JOIN operations on the enrollment individuals. For example, the query that shows all the student names and their grade along with the semester time for a particular course (e.g., Semantic Web Technology) is written as follows:
PREFIX : <http://obda.inf.unibz.it/university/enrollment.owl#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> select distinct $name $semester $year $grade where { $a :courseName "Semantic Web Technology" . $enrollment :hasCourse $a; :score $grade . $enrollment :hasSemester $c . $c :semesterYear $year; :semesterCount $semester . $d :applies $enrollment; :lastName $name }
As an exercise, try to create a query that retrieves a student report showing course names and the grades from a particular student. It is possible that you will retrieve a same course name because the student repeated the course due failing. Cross-checked your answer by looking at our OBDA file.
- StudentEnrollment.owl. The ontology file.
- StudentEnrollment.obda. The mappings file.
- StudentEnrollment.q. The sample queries file.
- enrollment.sql. The data source
- Quick Start Guide
- Easy-Tutorials
- More Tutorials
- Examples
- FAQ
- Using Ontop
- Learning more
- Troubleshooting
- Developer Guides
- Links