RDF 能否对带边属性的标记 属性 图建模?
Can RDF model a labeled property graph with edge properties?
我想像下面这样建模合作伙伴关系,我用标记的 属性 图表的格式表示。
我想用RDF语言来表达上面的图,特别想知道我是否可以表达"loves"边的标签(这是一个article/letter的URI)。
我是RDF新手,我知道RDF可以很方便的表达LPG中的节点属性,但是是否可以方便的表达边属性呢?
这个问题的更多上下文:我想使用 RDF(而不是 Gremlin)的原因是我想在长 运行.
中添加一些推理能力
补充问题:如果我们选择一个RDF模型来表示上述LPG,用简单的英语,我想用SPARQL查询来回答以下问题:
- 鲍勃爱上谁了吗?
- 如果是,他爱的是谁,为什么?
查询 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 系统中使用它!
AnzoGraph支持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
我想像下面这样建模合作伙伴关系,我用标记的 属性 图表的格式表示。
我想用RDF语言来表达上面的图,特别想知道我是否可以表达"loves"边的标签(这是一个article/letter的URI)。
我是RDF新手,我知道RDF可以很方便的表达LPG中的节点属性,但是是否可以方便的表达边属性呢?
这个问题的更多上下文:我想使用 RDF(而不是 Gremlin)的原因是我想在长 运行.
中添加一些推理能力补充问题:如果我们选择一个RDF模型来表示上述LPG,用简单的英语,我想用SPARQL查询来回答以下问题:
- 鲍勃爱上谁了吗?
- 如果是,他爱的是谁,为什么?
查询 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 系统中使用它!
AnzoGraph支持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