RDF 能否对带边属性的标记 属性 图建模?

Can RDF model a labeled property graph with edge properties?

我想像下面这样建模合作伙伴关系,我用标记的 属性 图表的格式表示。

我想用RDF语言来表达上面的图,特别想知道我是否可以表达"loves"边的标签(这是一个article/letter的URI)。

我是RDF新手,我知道RDF可以很方便的表达LPG中的节点属性,但是是否可以方便的表达边属性呢?

这个问题的更多上下文:我想使用 RDF(而不是 Gremlin)的原因是我想在长 运行.

中添加一些推理能力

补充问题:如果我们选择一个RDF模型来表示上述LPG,用简单的英语,我想用SPARQL查询来回答以下问题:

  1. 鲍勃爱上谁了吗?
  2. 如果是,他爱的是谁,为什么?

查询 loveletters.com/123 的 SPARQL 语句有多复杂?

RDF 不支持边缘属性,因此简短的回答是否定的。但是当然有很多方法可以在 RDF 中对这种事情进行建模。

没有边属性的普通 RDF 三元组

如果我们不想注释边,Bob 和 Mary 之间的关系将只是一个三元组,Bob 是主语,Mary 是宾语,“爱”是谓语:

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

person:Bob :loves person:Mary.

那么如何添加注释呢?

选项 1:使用 RDF 具体化

RDF 有一个名为“RDF reification”的内置解决方案。它允许对语句进行声明:

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>.

所以我们说有一个语句,Bob 是主语,Mary 是宾语,“loves”是谓语。然后我们可以向该语句添加属性。缺点是它有点多余。首先我们添加“loves”三元组,然后再添加四个三元组来复制“loves”三元组。

选项 2:将关系建模为实体

另一种方法是改变模型。我们不认为“爱”是人与人之间的边缘,而是将其视为一个节点。代表关系的节点,连接到相关的两方。

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

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

所以在我们的模型中,我们创建了一个 class :LovesRelationship 来表示“爱”,属性 :who:whom 来表示双方。这种方法的缺点是图形结构不再直接代表我们的社交网络。所以在查询两个人之间的关系时,我们总是要遍历那些关系实体,而不仅仅是处理连接人的边。

选项 3:使用 RDF*

a proposal called RDF* 很好地解决了这个问题。 (有时它被称为 RDR 或 Reification Done Right。)RDF*/RDR 添加了允许三元组成为其他三元组主题的新语法:

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

缺点是它是非标准的,目前只有少数系统支持 (Blazegraph, AnzoGraph, and an extension for Jena)。截至 2019 年 4 月,海王星不在其中。

查询:鲍勃有没有爱上任何人?

这在基本 RDF 版本以及选项 1 和选项 3 中很容易做到:

ASK { person:Bob :loves ?anyone }

选项 2 需要不同的查询,因为更改了模型:

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

这将匹配任何 :LovesRelationship,其中 :who 属性 是 Bob,无论 :whom:reason 属性如何。

查询:Bob 爱上了谁,为什么?

选项 1,RDF 具体化:

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

我觉得这个查询不是很直观,因为它讨论的是 RDF 语句,而我们真正感兴趣的是人和关系。

选项 2,建模为实体的关系:

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

这在我看来更好;一旦您接受关系是此模型中的实体,它就会变得相当直观。

选项 3,RDF*,使用 SPARQL*:

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

这是简洁直观的,很遗憾我们目前不能在大多数 SPARQL 系统中使用它!

A​​nzoGraph支持RDF*/SPARQL*,因此您实际上可以使用最简洁、最直观的格式来表示数据并进行查询。

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> .
}

现在查询:

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

结果:

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