如果我将ABC和CDE类定义为A,B,C,D,E类的交叉点,如下所示:
<Class rdf:about="&blah;ABC">
<equivalentClass>
<Class>
<intersectionOf rdf:parseType="Collection">
<Restriction>
<onProperty rdf:resource="&blah;hasMarker"/>
<someValuesFrom rdf:resource="&blah;A"/>
</Restriction>
<Restriction>
<onProperty rdf:resource="&blah;hasMarker"/>
<someValuesFrom rdf:resource="&blah;B"/>
</Restriction>
<Restriction>
<onProperty rdf:resource="&blah;hasMarker"/>
<someValuesFrom rdf:resource="&blah;C"/>
</Restriction>
</intersectionOf>
</Class>
</equivalentClass>
</Class>
<Class rdf:about="&blah;CDE">
<equivalentClass>
<Class>
<intersectionOf rdf:parseType="Collection">
<Restriction>
<onProperty rdf:resource="&blah;hasMarker"/>
<someValuesFrom rdf:resource="&blah;C"/>
</Restriction>
<Restriction>
<onProperty rdf:resource="&blah;hasMarker"/>
<someValuesFrom rdf:resource="&blah;D"/>
</Restriction>
<Restriction>
<onProperty rdf:resource="&blah;hasMarker"/>
<someValuesFrom rdf:resource="&blah;E"/>
</Restriction>
</intersectionOf>
</Class>
</equivalentClass>
</Class>
如何查询SPARQL中给定输入类集满足其限制的所有交集类?例如,如果我将A,B,C,D,E,F,G输入此查询,我希望能够回来
ABC A
B
C
CDE C
D
E
另外两个皱纹:如果我查询A,Z,C,其中Z是B的等价类,那么这应该匹配并理想地返回
ABC A
Z
C
其次,结果应该只返回最大匹配;因此,如果存在ABCD类并且我在A,B,C,D之间进行查询,则它将返回ABCD而不是ABC。
提前致谢!
更新
为了澄清,除非所有组成类都在提供的输入列表中,否则我不希望与交集类匹配。例如,如果我向查询提供A,B,我不想让ABC回来。如果我提供A,B,C,D,我确实想要回ABC。
我的用例是这样的:我有一组数据点,在每个数据点中我都识别出一组任意的基本概念A,B,C,D ......等等,每个都有不同的可能性。我想问一下本体“这个列表包含哪些更高级别的概念(即交叉点)?”
目前,我的查询看起来像这样(考虑到我在上面概述的本体中的限制和onProperty):
SELECT DISTINCT ?intclass ?inputclasses
WHERE
{
?intclass owl:equivalentClass /
owl:intersectionOf /
rdf:rest*/rdf:first /
owl:someValuesFrom ?inputclasses
}
ORDER BY ?intclass
BINDINGS ?inputclasses { (:A) (:B) (:C) (:D) }
不幸的是,这回馈了我的本体中包含任何输入类的每个交集。我认为这是因为rest / first依次对输入列表依次评估每个交集的组成类,如果找到任何一个,则匹配。
我想要做的是(a)只有当交集中的所有类都出现在输入列表中时才会匹配,(b)推断来自类的匹配等效于输入列表中的类,(c)返回交集类以及与其匹配的输入列表中的类子集。也许这只是通过SPARQL不可行的?
答案 0 :(得分:2)
首先,我不认为你能够完成你想做的事情,但我认为你能够相当接近。特别是,我认为你提到的最大限度约束将特别难以实现。通过这种方式处理SPARQL中的一组内容通常很困难。尽管如此,我们可以看到我们能做些什么。
使用我们可以实际使用的一些示例数据来回答这些问题要容易得多。我也从简化问题开始,因此ABC只是A,B和C的交叉点,以及C,D和E的CDE。目前还没有限制类(它们赢得了&t; t实际上增加了很多复杂性。出于测试目的(能够确保我们的查询不会返回不想要的值),我还添加了类F和DEF。在Turtle序列化中查看数据也更容易,因为它更接近SPARQL模式语法。这是简化的本体论:
@prefix : <http://stackoverflow.com/q/22396095/1281433/intersections#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
<http://stackoverflow.com/q/22396095/1281433/intersections>
a owl:Ontology .
:A a owl:Class .
:B a owl:Class .
:C a owl:Class .
:D a owl:Class .
:E a owl:Class .
:F a owl:Class .
:ABC a owl:Class ;
owl:equivalentClass [ a owl:Class ;
owl:intersectionOf ( :A :B :C )
] .
:CDE a owl:Class ;
owl:equivalentClass [ a owl:Class ;
owl:intersectionOf ( :C :D :E )
] .
:DEF a owl:Class ;
owl:equivalentClass [ a owl:Class ;
owl:intersectionOf ( :D :E :F )
] .
对于每个等同于交集类的类,有一个从类到每个相交类的路径。我们可以利用这个事实来找到相当于包含A,B和C的交叉点的任何类:
prefix : <http://stackoverflow.com/q/22396095/1281433/intersections#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select distinct ?class where {
?class owl:equivalentClass/
owl:intersectionOf/
rdf:rest*/rdf:first :A, :B, :C .
}
---------
| class |
=========
| :ABC |
---------
但是,这并不能找到CDE,因为此查询要求的内容具有指定值的 all 。听起来你想要的是要求具有至少一个指定值的东西,而不是非指定值。您可能需要两次编写类列表,但您可以这样做:
prefix : <http://stackoverflow.com/q/22396095/1281433/intersections#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?class ?i where {
values ?i { :A :B :C :D :E }
?class owl:equivalentClass/
owl:intersectionOf/
rdf:rest*/rdf:first ?i .
filter not exists {
?class owl:equivalentClass/
owl:intersectionOf/
rdf:rest*/rdf:first ?j .
filter( !(?j in (:A, :B, :C, :D, :E )) )
}
}
order by ?class ?i
--------------
| class | i |
==============
| :ABC | :A |
| :ABC | :B |
| :ABC | :C |
| :CDE | :C |
| :CDE | :D |
| :CDE | :E |
--------------
请注意,DEF不在结果中,因为虽然它有D和E,但它的值也不是任何指定的类,F。
由于我们过滤掉了输入列表中包含 元素的每个交集类,我们保证我们保留的每个交集类在输入列表中只有 的元素。鉴于这种措辞,我们实际上可以使查询更简单:
prefix : <http://stackoverflow.com/q/22396095/1281433/intersections#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?class ?i where {
# find each ?class that's equivalent to an intersection
?class owl:equivalentClass/owl:intersectionOf ?list .
# and grab the intersecting classes for the results
?list rdf:rest*/rdf:first ?i .
# but filter out any ?class that has an intersecting
# class that's not in the input list.
filter not exists {
?list rdf:rest*/rdf:first ?element .
filter( !(?element in (:A, :B, :C, :D, :E )) )
}
}
--------------
| class | i |
==============
| :ABC | :A |
| :ABC | :B |
| :ABC | :C |
| :CDE | :C |
| :CDE | :D |
| :CDE | :E |
--------------
这可能效率较低,因为现在您正在找到每个交集类并过滤掉不合格的交集类,而不是只找到可能可接受的那些,然后过滤掉一些。这有多大可能取决于您的实际数据。
我认为这回答了你问题的主要部分。要处理限制的交集,您只需要注意所讨论的类之间的路径有点不同。您希望匹配列表元素的owl:someValuesFrom
属性的值,而不是匹配列表中的元素,因此路径需要最终owl:someValuesFrom
:
?class owl:equivalentClass/
owl:intersectionOf/
rdf:rest*/rdf:first/
owl:someValuesFrom ?i .
如果我查询A,Z,C,其中Z是B的等价类,那么这个 应匹配并理想地返回
ABC A Z C
这里的查询开始变得有点复杂,但它仍然可以管理。诀窍在于,不是选择?i
作为交集列表的简单成员,而是需要选择?i
作为列出交集列表元素等效的输入的成员。然后,过滤 out 交叉点也有点复杂。您需要确保有 no 元素,以使输入列表的 no 元素等同于intersection元素。把这些放在一起,你会得到这个问题:
prefix : <http://stackoverflow.com/q/22396095/1281433/intersections#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?class ?i where {
?class owl:equivalentClass/
owl:intersectionOf ?list .
?list rdf:rest*/rdf:first/(owl:equivalentClass|^owl:equivalentClass)* ?i .
filter( ?i in (:A, :B, :C, :D, :E ))
filter not exists {
?list rdf:rest*/rdf:first ?element .
filter not exists {
?element (owl:equivalentClass|^owl:equivalentClass)* ?j
filter( ?j in (:A, :B, :C, :D, :E ))
}
}
}
如果添加以下数据
:Z a owl:Class ;
owl:equivalentClass :B .
:AZC a owl:Class ;
owl:equivalentClass [ a owl:Class ;
owl:intersectionOf ( :A :Z :C )
] .
然后你会得到这些结果:
--------------
| class | i |
==============
| :ABC | :A |
| :ABC | :B |
| :ABC | :C |
| :AZC | :A |
| :AZC | :B |
| :AZC | :C |
| :CDE | :C |
| :CDE | :D |
| :CDE | :E |
--------------
这可能不会太难(尽管获得最终查询会有点棘手)。重要的是,等效的类将通过路径(owl:equivalentClass|^owl:equivalentClass)*
相关联。
其次,结果应该只返回最大匹配;所以,如果有 存在一个ABCD类,我查询A,B,C,D,它将返回ABCD 而不是ABC。
如果你能做到这一点,这部分可能会相当困难。 SPARQL实际上并不是为处理这种查询而设计的。可以很容易地计算交集类相交的类数,但是如果可以的话,比较这些子集关系的集合会相当困难。