SPARQL使用带有限制的子查询

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPARQL使用带有限制的子查询相关的知识,希望对你有一定的参考价值。

我正在开发一个Java应用程序,它使用ARQ通过TDB上的Fuseki端点执行SPARQL查询。

该应用程序需要一个查询,返回每个人和出生在同一个地方的其他人的出生地。

首先,我编写了这个SPARQL查询,它返回person_ids和每个人的出生地。

prefix fb: <http://rdf.freebase.com/ns/>
prefix fn: <http://www.w3.org/2005/xpath-functions#>
select ?person_id ?place_of_birth 
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 10

----------------------------------
| person_id    | place_of_birth  |
==================================
| fb:m.01vtj38 | "El Centro"@en  |
| fb:m.01vsy7t | "Brixton"@en    |
| fb:m.09prqv  | "Pittsburgh"@en |
----------------------------------

在那之后,我添加了一个子查询(https://jena.apache.org/documentation/query/sub-select.html)添加了出生在那里的其他人,但我得到的不止一个人相关,我只需要一个。

prefix fb: <http://rdf.freebase.com/ns/>
prefix fn: <http://www.w3.org/2005/xpath-functions#>
select ?person_id ?place_of_birth ?other_person_id
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    {
       select  ?other_person_id
       where {
       ?place_of_birth_id fb:location.location.people_born_here ?other_person_id .
       }
     }
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 10

---------------------------------------------------
| person_id    | place_of_birth | other_person_id |
===================================================
| fb:m.01vtj38 | "El Centro"@en | fb:m.01vtj38    |
| fb:m.01vtj38 | "El Centro"@en | fb:m.01vsy7t    |
| fb:m.01vtj38 | "El Centro"@en | fb:m.09prqv     |
---------------------------------------------------

我试图添加一个LIMIT 1子查询,但它似乎不起作用(查询已执行但永远不会结束)

prefix fb: <http://rdf.freebase.com/ns/>
prefix fn: <http://www.w3.org/2005/xpath-functions#>
select ?person_id ?place_of_birth ?other_person_id
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    {
       select  ?other_person_id
       where {
       ?place_of_birth_id fb:location.location.people_born_here ?other_person_id .
       }
       LIMIT 1
     }
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 3

有没有办法在子查询中只返回一个结果,或者我不能使用SPARQL。

答案

您可以在子查询中使用限制

您可以在子查询中使用限制。这是一个例子:

select ?x ?y where {
  values ?x { 1 2 3 4 }
  {
    select ?y where {
      values ?y { 5 6 7 8 }
    }
    limit 2
  }
}
limit 5
---------
| x | y |
=========
| 1 | 5 |
| 1 | 6 |
| 2 | 5 |
| 2 | 6 |
| 3 | 5 |
---------

正如您所看到的,您从子查询(5和6)中获取两个值,并且这些值与外部查询的绑定相结合,从中我们总共得到五行(由于限制)。

子查询首先在最里面进行评估

但是,请记住,子查询从最里面的第一个到最外面进行评估。这意味着在您的查询中,

select ?person_id ?place_of_birth ?other_person_id
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    {
       select  ?other_person_id
       where {
       ?place_of_birth_id fb:location.location.people_born_here ?other_person_id .
       }
       LIMIT 1
     }
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 3

你找到一个匹配

?place_of_birth_id fb:location.location.people_born_here ?other_person_id .

并将?other_person_id绑定传递给外部查询。但是,外部查询的其余部分不使用?other_person_id,因此它对结果没有任何影响。

该怎么做

If you need only one other person

该应用程序需要一个查询,返回每个人和出生在同一个地方的其他人的出生地。

从概念上讲,你可以把这看作是挑选一个人,找到他们的出生地,并从那个地方出生的人中抽取一个人。你也可以这样写这样的查询:

select ?person_id ?place_of_birth (sample(?other_person_idx) as ?other_person_id)
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    FILTER (langMatches(lang(?place_of_birth),"en"))
    ?place_of_birth_id fb:location.location.people_born_here ?other_person_idx .
    filter ( ?other_person_idx != ?person_id )
}
group by ?person_id ?place_of_birth

If you need more than one

如果每个结果需要多个“其他结果”,这是一个非常棘手的问题。那是Nested queries in sparql with limits的问题。在How to limit SPARQL solution group size?有一种可用于此的方法。

以上是关于SPARQL使用带有限制的子查询的主要内容,如果未能解决你的问题,请参考以下文章

使用 WikiData Sparql 高效查询抽象元素

如何将 Sparql 查询结果存储到数组中?

Sparql查询RDF

SPARQL - 未知的名称空间前缀错误

知识图谱学习与实践——通过例句介绍Sparql的使用

本体限制对 SPARQL 最终结果的影响