考虑列出人员(父母)及其职位(儿童)。
请注意,我已经简化了示例,但它可能是parent-child-childofChild-etc,因此某些实体具有子树。
我想有一个查询返回一些过滤(在某些条件下)人ID和它们的帖子ID的联合,如下所示:
person1Id
person2Id
person1Post1Id
person1Post2Id
.......
鉴于具有3人(具有房产年龄,姓名)的具体情况,其中Person1有2个帖子而其他人没有帖子我设法以2种方式做到这一点,但两者都有限制。所以在where子句中我们有:
?entityId ?p ?o.
{
#persons/posts graph pattern
}
filter (?entityId =?person || ?entityId=?post) # || otherChildFitler
这有效,但使用过滤器,所以我想避免使用union:
{
SELECT (?person as ?s) WHERE{ #criteria}
order by ...
limit 1
}
UNION
{
{
SELECT ?person WHERE{ #criteria}
order by ...
limit 1
}
?s a <http://www.example.org/schema/Post> .
?s <http://www.example.org/schema/postedBy> ?person .
}
这也有效,但我必须为每个孩子复制人物内部查询。 所以我尝试以某种方式使用bind如此: (假设内部查询返回1个有2个帖子的人。)
select ?s ?person ?projectedOutPerson
where
{
#tag 1
{
#returns 1 person with 2 posts
SELECT ?person WHERE
{
?person a <http://www.example.org/schema/Person> .
optional{?person <http://www.example.org/schema/age> ?age.}
}
order by desc(?age)
limit 1
}
#tag 2
bind(?person as ?projectedOutPerson)
#tag 3
{
bind(?projectedOutPerson as ?s)
}
#tag 4
UNION
{
?s a <http://www.example.org/schema/Post> .
?s <http://www.example.org/schema/postedBy> ?projectedOutPerson.
}
#tag 5
}
这会重新发布帖子ID,但不添加personIds,并且有一些奇怪的行为。
我在bigdata 1.3和stardog 2上进行测试。
?如果我选择没有帖子的人没有回复帖子,那么projectionOutPerson就会被绑定(标签2-3)。
在两个db中,tag3-4之间的绑定没有完成/加入所以?s没有绑定到某个人(返回空结果)。
如果我删除部分标签4-5 bigdata显示选定人(所以现在绑定标签3-4工作)但stardog返回(空结果,person1,person1)所以在stardog链接绑定不起作用
bind(?person as ?p1) #only this is bound
bind(?p2 as ?p3)
bind(?p3 as ?s)
在sparql1.1 docs中“BIND子句引入的变量不得在组图形模式中使用到BIND中的使用点。”但每次引入新变量时,我认为应该工作
那么如何在不重复子查询或使用过滤器的情况下解决这个问题。
答案 0 :(得分:1)
如果提供一些数据,回答这类问题要容易得多。如果我正确理解您的问题,您会得到以下数据。我在Turtle中提供它,因为它具有相当人性化的可读性。
@prefix : <http://stackoverflow.com/q/21115947/1281433/> .
# person1 has two posts, person2 has one post, and
# person3 has no posts at all.
:person1 a :Person ;
:hasPost :person1post1 , :person1post2 .
:person2 a :Person ;
:hasPost :person2post1 .
:person3 a :Person .
现在,如果您想要选择每个人及其所有帖子,您可以使用以下查询来执行此操作:
prefix : <http://stackoverflow.com/q/21115947/1281433/>
select ?id where {
?person a :Person ;
:hasPost? ?id .
}
-----------------
| id |
=================
| :person3 |
| :person2 |
| :person2post1 |
| :person1 |
| :person1post2 |
| :person1post1 |
-----------------
这里的诀窍在于查询模式
?person a :Person ;
:hasPost? ?id .
?person a :Person
确保?person
是一个人。然后,模式?person :hasPost? ?id
找到?id
s,以便存在从?person
到?id
的长度为零或一的路径。长度为零的情况意味着?id
可以绑定到?person
的相同值。长度为1的情况意味着您将获得x
的所有?person :hasPost x
。
现在,就个人和帖子而言,谈论有其他帖子的帖子并没有多大意义(我认为),但如果你只是在树形结构中寻找后代,你可以在您的媒体资源路径中使用*
代替?
。例如,如果您有这些数据:
@prefix : <http://stackoverflow.com/q/21115947/1281433/> .
# 1
# / \
# / \
# 2 3
# / \ / \
# 4 5 6 7
# \ \ \
# 8 9 10
:node1 :hasChild :node2 , :node3 .
:node2 :hasChild :node4 , :node5 .
:node3 :hasChild :node6 , :node7 .
:node4 :hasChild :node8 .
:node6 :hasChild :node9 .
:node7 :hasChild :node10 .
您可以使用以下查询获取:node3
及其所有后代:
prefix : <http://stackoverflow.com/q/21115947/1281433/>
select ?node where {
:node3 :hasChild* ?node
}
-----------
| node |
===========
| :node3 |
| :node7 |
| :node10 |
| :node6 |
| :node9 |
-----------