2013-07-03 254 views
1

我有一个简单的SPARQL查询:SPARQL“for循环”查询

SELECT DISTINCT ?class1 ?class2 
    WHERE { 
     ?class1 :child ?attribute1 . 
     ?class2 :child ?attribute2 . 
     ?attribute1 :objectName ?name1 . 
     ?attribute2 :objectName ?name2 . 
     FILTER (?name1 = ?name2) 
    } 

在一个RDF图,其中,这些“类”的一个可以有多个孩子。我想要做的是找到重复的类,其中重复的意思是一个类中的所有子类(由objectName标识)都在另一个类中。

它所做的是,返回至少有一个孩子在另一个班级中存在的每个班级。

所以我正在寻找某种迭代每个类的所有孩子,但我还找不到方法。如果有人能帮忙,会很棒。

感谢

+0

有关于计算SPARQL子集的[最近的问题](http://stackoverflow.com/questions/17323636/comparing-sparql-graphs/17344570#17344570)。这个问题涉及到检查一个命名图是否是另一个命名图的子集,但是其中一些技术可能适用于这里,您要查找该集{'?x':'class1:child?x'}是否为子集{'?x':'class2:child?x'}。 –

+0

你说过“重复”班,但是“所有一个班的孩子都在另一班。”除非所有第二班的孩子都在第一堂课,否则你只会谈论_sub_-class,而不是_equivalent_-class。你打算如何? –

回答

1

下面是一些包含四个类的示例数据。第一类和第二类包含名称为“name1”和“name2”的孩子。第三类包含“name1”和“name3”,第四类包含“name3”和“name4”。第五类包含第四类的所有孩子,以及“name5”。所以,第一类和第二类是等价的,第四类是第五类的子类。

@prefix : <http://example.org/> . 

:class1 :child [ :objectName "name1" ] , 
       [ :objectName "name2" ] . 

:class2 :child [ :objectName "name2" ] , 
       [ :objectName "name1" ] . 

:class3 :child [ :objectName "name1" ] , 
       [ :objectName "name3" ] . 

:class4 :child [ :objectName "name3" ] , 
       [ :objectName "name4" ] . 

:class5 :child [ :objectName "name3" ] , 
       [ :objectName "name4" ] , 
       [ :objectName "name5" ] . 

你的描述听起来像你实际上是寻找子类,因为你提到的类其所有的孩子也在另一个类。因此,该SPARQL查询应该找到的子类关系的护理:

prefix : <http://example.org/> 

select distinct ?c1 ?c2 where { 
    ?c1 :child [] . 
    ?c2 :child [] . 
    NOT EXISTS { ?c1 :child [ :objectName ?name ] . 
       NOT EXISTS { ?c2 :child [ :objectName ?name ] } } 
    FILTER(!sameTerm(?c1, ?c2)) 
} 

嵌套NOT EXIST模式确保我们选择的唯一类是这样的,有做NOT EXIST元素?c1这确实NOT EXIST?c2。也就是说,我们拒绝任何成对的集合,其中?c1中的元素,其不在?c2中;我们拒绝任何?c1,?c2对,其中?c1?c2一个子集,因此我们保持只是那些地方?c1?c2一个子集。 sameTerm过滤器会删除简单的?c,?c对,因为所有内容都是其自身的子集。耶拿使用的命令行工具ARQ,我们得到这些结果:

$ arq --data data.n3 --query query.sparql 
--------------------- 
| c1  | c2  | 
===================== 
| :class4 | :class5 | 
| :class2 | :class1 | 
| :class1 | :class2 | 
--------------------- 

正如预期的那样,:class1:class2是其他的每个子集,并:class4:class5一个子集。

如果你想等价类,它是足够的,只是第二NOT EXISTS确保?c2也是?c1一个子集:

prefix : <http://example.org/> 

select distinct ?c1 ?c2 where { 
    ?c1 :child [] . 
    ?c2 :child [] . 
    NOT EXISTS { ?c1 :child [ :objectName ?name ] . 
       NOT EXISTS { ?c2 :child [ :objectName ?name ] } } 
    NOT EXISTS { ?c2 :child [ :objectName ?name ] . 
       NOT EXISTS { ?c1 :child [ :objectName ?name ] } } 
    FILTER(!sameTerm(?c1, ?c2)) 
} 

有了这个查询,我们回来只是:class1:class2

$ arq --data data.n3 --query query.sparql 
--------------------- 
| c1  | c2  | 
===================== 
| :class2 | :class1 | 
| :class1 | :class2 | 
--------------------- 
+0

谢谢,这正是我需要的。澄清一下,我没有谈论子集,因为基本上我是在查询之后给了我所有完全相同的类,但是从这一点来看,这已经不再适用了。 – Grochni

+0

@Grochni很高兴听到它!我更新了答案以显示等效的类查询(但是,正如您指出的,在子类查询之后它非常简单)。 –

2

注意SPARQL是一个说明性语言,而不是一个势在必行,所以没有遍历东西的概念。你可以在API中将它做到RDF存储中,但至少在理论上用SPARQL表达它会更有效率。

我认为你需要做的是找到所有类的组合,并减去某些objectName不同的那些组合。

以下是完全未经测试的!

SELECT DISTINCT ?class1 ?class2 
WHERE { 
    ?class1 :child ?attribute1 . 
    ?class2 :child ?attribute2 . 
    MINUS { 
     ?attribute1 :objectName ?name1 . 
     ?attribute2 :objectName ?name2 . 
     FILTER (?name1 != ?name2 && ?attribute1 = ?attribute2) 
    } 
} 

有一个很小的机会是正确的:)但它应该给你一些启发。

+0

我不知道MINUS,这是pritty有用,所以谢谢。但问题是每个匹配的孩子仍然有一个结果,所以如果其中一个孩子在另一个班级中找到,那么这些班级将被视为重复。 – Grochni