12

I wanted to model partner relationship like the following, which I expressed in the format of labeled property graph.

enter image description here

I wanted to use RDF language to express the above graph, particularly I wanted to understand if I can express the label of the "loves" edge (which is an URI to an article/letter).

I am new to RDF, and I know the RDF can easily express the node properties in the LPG, but is it possible to conveniently express the edge properties?

A bit more context of this question: the reason I wanted use RDF (rather than Gremlin) is that I wanted to add some reasoning capability in the long run.

Further added question: if we choose an RDF model to represent the above LPG, in plain English, I wanted to answer the following questions with SPARQL query:

  1. Is Bob in love with any one?
  2. If so, who is he in love with and why?

How complex would the SPARQL statement be to query out the loveletters.com/123?

chen
  • 4,302
  • 6
  • 41
  • 70
  • You can use the property also as subject of an RDF triple. But in your case, you have to use reification given that you want to make a statement about a particular triple. Recently, (ok, the work startet somewhere in 2013/14 iirc) Olaf Hartig and some others introduced an alternative called RDF* and SPARQL* where you basically can use full RDF triples in subject or object position. A recnt blog post is [here](http://blog.liu.se/olafhartig/2019/01/10/position-statement-rdf-star-and-sparql-star/) - that said, a triple store has to support this non-standard language extension. – UninformedUser Apr 28 '19 at 07:09
  • Jena and Blazegraph do support RDF*/SPARQL* so far. Moreover, none of the approaches I mentioned will be taken into account during standard reasoning (at least not by RDFS, OWL RL or whatever) – UninformedUser Apr 28 '19 at 07:11
  • 2
    @AKSW Small correction: Blazegraph and AnzoGraph support RDF*. Jena does not, but [there is an open-source project](https://github.com/RDFstar/RDFstarTools) that extends Jena with support for RDF*. – cygri Apr 28 '19 at 11:00
  • @ ok, yeah - sorry, it's an extension of Jena. Thought it already made it into the main project. Looking at the project, I'm wondering whether it could be really used as an extension, i.e. in combination with Fuseki. The project also needs to keep in sync with Jena main. – UninformedUser Apr 28 '19 at 12:46
  • Possible duplicate of [How can I express additional information (time, probability) about a relation in RDF?](https://stackoverflow.com/questions/32923213/how-can-i-express-additional-information-time-probability-about-a-relation-in) – Jeen Broekstra Jun 04 '19 at 01:39

2 Answers2

20

RDF doesn't support edge properties, so the brief answer is no. But of course there are ways to model this kind of thing in RDF.

Plain RDF triple without edge properties

If we didn't want to annotate the edge, the relationship between Bob and Mary would simply be a triple with Bob as Subject, Mary as object, and “loves” as predicate:

PREFIX : <http://example.org/ontology#>
PREFIX person: <http://example.org/data/person/>

person:Bob :loves person:Mary.

So how can we add annotations?

Option 1: Using RDF Reification

RDF has a built-in solution called “RDF reification”. It allows making statements about statements:

PREFIX : <http://example.org/ontology#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX person: <http://example.org/data/person/>
PREFIX statement: <http://example.org/data/statement/>

person:Bob :loves person:Mary.

statement:1 a rdf:Statement;
    rdf:subject person:Bob;
    rdf:predicate :loves;
    rdf:object person:Mary;
    :reason <http://loveletters.com/123>.

So we say that there is a statement with Bob as subject, Mary as object, and “loves” as predicate. Then we can add properties to that statement. The downside is that it is kind of redundant. First we add the “loves” triple, then we add four more triples to replicate the “loves” triple.

Option 2: Modelling relationships as entities

Another approach is to change the model. Instead of considering “loves” an edge between people, we consider it a node in itself. A node that represents the relationship, and is connected to the two parties involved.

PREFIX relationship: <http://example.org/data/relationship/>

relationship:1 a :LovesRelationship;
    :who person:Bob;
    :whom person:Mary;
    :reason <http://loveletters.com/123>.

So in our model we created a class :LovesRelationship that represents “loves”, and properties :who and :whom to indicate the two parties. The downside of this approach is that the graph structure no longer directly represents our social network. So when querying how two people are related, we always have to go through those relationship entities instead of just dealing with edges connecting people.

Option 3: Using RDF*

There is a proposal called RDF* that addresses this problem quite nicely. (Sometimes it's called RDR or Reification Done Right.) RDF*/RDR adds new syntax that allows triples to be the subject of other triples:

<<person:Bob :loves person:Mary>>
    :reason <http://loveletters.com/123>.

The downside is that it is non-standard and so far supported only by a few systems (Blazegraph, AnzoGraph, and an extension for Jena). As of April 2019, Neptune is not among them.

Query: Is Bob in love with anyone?

This is easy to do in the basic RDF version as well as in Option 1 and Option 3:

ASK { person:Bob :loves ?anyone }

Option 2 requires a different query, because of the changed model:

ASK {
   ?rel a :LovesRelationship;
       :who person:Bob.
}

This would match any :LovesRelationship where the :who property is Bob, regardless of the :whom and :reason properties.

Query: Who is Bob in love with and why?

Option 1, RDF Reification:

SELECT ?whom ?why {
    ?statement a rdf:Statement;
        rdf:subject person:Bob;
        rdf:predicate :loves;
        rdf:object ?whom;
        :reason ?why.
}

I find this query not very intuitive, because it talks about RDF statements, while we are really interested in people and relationships.

Option 2, relationship modelled as entity:

SELECT ?whom ?why {
    ?rel a :LovesRelationship;
        :who person:Bob;
        :whom ?whom;
        :reason ?why.
}

This is better in my eyes; once you have accepted that relationships are entities in this model, it becomes fairly intuitive.

Option 3, RDF*, using SPARQL*:

SELECT ?whom ?why {
    <<person:Bob :loves ?whom>>
        :reason ?why.
}

This is concise and intuitive, so it's a shame we can't currently use it in most SPARQL systems!

cygri
  • 9,412
  • 1
  • 25
  • 47
  • many thanks for the detail explanation! By looking at the above three options, it seems to me that I should be using Option 1 because I wanted to have a simple model (and hopefully later be able to reason / inference about my graph). With Option 1, can `reason ` be easily queried out? -- Let me update my question and if you could give an updated answer, that would be much appreciated. – chen Apr 28 '19 at 23:07
  • 1
    @chen I've extended the answer. – cygri Apr 29 '19 at 08:35
  • How can this be modeled in xml format ?? Any suggestions ? – Malay Revanth Oct 16 '20 at 17:12
0

AnzoGraph supports RDF*/SPARQL*, so you could actually use the concise and most intuitive format to represent the data and query it.

insert data {
  :Bob a :Person; <name> "Bob"; <state> "CA" .
  :Mary a :Person; <name> "Mary"; <state> "CA" .
  :Bob <loves> :Mary .
  << :Bob <loves> :Mary >> <reason> <http://loveletters.com/123> .
}

Now query:

select ?who ?whom ?reason
where {
  ?p1 a :Person ; <name> ?who .
  ?p2 a :Person ; <name> ?whom .
  << ?p1 <loves> ?p2 >> <reason> ?reason .
}

Result:

 who | whom | reason                     
-----+------+----------------------------
 Bob | Mary | http://loveletters.com/123 
1 rows