1

I'm trying to convert my current relational database to an RDF/OWL triple store. One thing that I'm running into is when I have a bridge/join table that has a composite/compound key of multiple values. For example, I have the following:

  • Equipment (EquipmentId)

  • EquipmentPoints (EquipmentId, PointId, CommodityId)

  • Point (PointId)

I'm unsure of how I would model the data in regards to saying Equipment :hasPoint ...? A particular point could be a different commodity depending on the type of equipment it is on.

Appreciate any help.

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
mike
  • 113
  • 1
  • 9
  • There are [keys](https://www.w3.org/TR/owl2-syntax/#Keys) in OWL, they might be composite, do not forget to make individuals different. But perhaps you should remodel things slightly, getting rid of this bridge table (in RDF, properties might have "multiple" values). In general, OWL is not a constraint language. – Stanislav Kralin Aug 22 '18 at 20:23
  • Stanislav, thank you for the response and link. When you say to make individuals different, do you suggest that I would instead make Points unique by possible modeling them uniquely - instead of PointA with many Commodity uses, create PointACommodityX, PointACommodityY, etc? This is a new concept for me and I'm still trying to pivot from a relational database viewpoint to a more semantic view of the data, and am kind of struggling. – mike Aug 22 '18 at 20:39

2 Answers2

2

First, perhaps you could remodel things, getting rid of :EquipmentPoints. They are possibly just artefacts of relational modeling. RDF properties may have multiple values. See here for more details.

For the sake of clarity, I'll simplify your data model slightly:

  • Equipment (EquipmentId)
  • EquipmentPoints (EquipmentId, PointId)
  • Point (PointId)

RDF

RDF is schemaless, there is no constraints in RDF.

You could model things as shown in another answer:

@prefix : <https://stackoverflow.com/q/51974155/7879193#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .

:equipment1 rdf:type :Equipment .
:equipment2 rdf:type :Equipment .

:point1 rdf:type :Point .
:point2 rdf:type :Point .

:equipmentPoint1 rdf:type :EquipmentPoint .
:equipmentPoint2 rdf:type :EquipmentPoint .

:equipmentPoint1 :hasEquipment :equipment1 ;
                 :hasPoint :point1 .

:equipmentPoint2 :hasEquipment :equipment1 ;
                 :hasPoint :point1 . # "constraint violation"

In order to define constraints, you could use languages like SHACL. Unfortunately, there is no core constraint components for compound keys in SHACL, one should use SPARQL-based constraints:

:EquipmentPointShape a sh:NodeShape ;
    sh:targetClass :EquipmentPoint ;
    sh:sparql [
        sh:message "Violation!" ;
        sh:severity sh:Violation ;
        sh:select """
                  SELECT ?this {
                      ?point1 ^:hasPoint  ?this, ?that .
                      ?equipment ^:hasEquipment  ?this, ?that .
                      FILTER (?this != ?that)
                  }
                  """
        ] .

OWL

OWL was designed for inferencing, not for constraint checking. See this answer for more details. However, you could use OWL 2 keys.

First, add some ontological "boilerplate":

[] rdf:type owl:Ontology .

:Equipment rdf:type owl:Class .
:Point rdf:type owl:Class .
:EquipmentPoint rdf:type owl:Class .

:hasPoint rdf:type owl:ObjectProperty .
:hasEquipment rdf:type owl:ObjectProperty .

:equipment1 rdf:type owl:NamedIndividual .
:equipment2 rdf:type owl:NamedIndividual .

:point1 rdf:type owl:NamedIndividual .
:point2 rdf:type owl:NamedIndividual .

:equipmentPoint1 rdf:type owl:NamedIndividual .
:equipmentPoint2 rdf:type owl:NamedIndividual .

Now you have correct Turtle-serialized ontology. Then add:

:EquipmentPoint owl:hasKey (:hasEquipment
                            :hasPoint
                           ) .

[ rdf:type owl:AllDifferent ;
  owl:distinctMembers (:equipmentPoint1
                       :equipmentPoint2
                      )
] .

A reasoner will infer that your ontology is inconsistent.


Note, there is no Unique Name Assumption and there is Open World Assumption in OWL.

After removing

[ rdf:type owl:AllDifferent ;
  owl:distinctMembers (:equipmentPoint1
                       :equipmentPoint2
                      )
] .

a reasoner will infer that

:equipmentPoint1 owl:sameAs :equipmentPoint2 .
Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
1

You need to think of the Semantic Web as a web, or graph, of data more so than a set of tables linked to one another via foreign keys.

The entities in your dataset can link to each other precisely like a website can link to another website. In that sense, there is no such thing as a primary key, or specially composite keys. There is just resources linking to each other.

In you case, I would probably model it like in the following example:

@base <http://example.com/resource/> .

<Equipment1> <hasId> "1" .
<Equipment1> <name> "Equipment 1" .
<Point1> <hasId> "1" .
<Point1> <description> "This is Point 1" .
<Equipment1> <hasEquipmentPoint> <EquipmentPoint1> .
<Point1> <hasEquipmentPoint> <EquipmentPoint1> .
<EquipmentPoint1> <hasCommodity> <Commodity1> .

Alternatively you could try to model it closer to the table you presented, and make the equipmentPoint link to the point and equipment instead:

<EquipmentPoint1> <hasEquipment> <Equipment1> .
<EquipmentPoint1> <hasPoint> <Point1> .
<EquipmentPoint1> <hasCommodity> <Commodity1> .

Obviously revamp names, etc. As you can see, there is no concept of keys, it is just a bunch of edges in a knowledge graph, which describes a link between two resources. Your table with composite keys could just be a separate resource, as I described above. There is no primary key, but it should still be possible to search through.

Chraebe
  • 429
  • 3
  • 12