SPARQL 使用带限制的子查询 [英] SPARQL using subquery with limit

查看:51
本文介绍了SPARQL 使用带限制的子查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

前缀 fb:前缀 fn:<http://www.w3.org/2005/xpath-functions#>选择 ?person_id ?place_of_birth在哪里 {?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 .过滤器(langMatches(lang(?place_of_birth),en"))}限制 10----------------------------------|person_id |place_of_birth |==================================|fb:m.01vtj38 |"El Centro"@zh ||fb:m.01vsy7t |"布里克斯顿"@zh ||fb:m.09prqv |"匹兹堡"@zh |----------------------------------

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

前缀 fb:前缀 fn:<http://www.w3.org/2005/xpath-functions#>选择 ?person_id ?place_of_birth ?other_person_id在哪里 {?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 .{选择 ?other_person_id在哪里 {?place_of_birth_id fb:location.location.people_born_here ?other_person_id .}}过滤器(langMatches(lang(?place_of_birth),en"))}限制 10--------------------------------------------------——|person_id |place_of_birth |other_person_id |===================================================|fb:m.01vtj38 |"El Centro"@zh |fb:m.01vtj38 ||fb:m.01vtj38 |"El Centro"@zh |fb:m.01vsy7t ||fb:m.01vtj38 |"El Centro"@zh |fb:m.09prqv |--------------------------------------------------——

我尝试添加 LIMIT 1 子查询,但似乎不起作用(查询已执行但从未结束)

前缀 fb:前缀 fn:<http://www.w3.org/2005/xpath-functions#>选择 ?person_id ?place_of_birth ?other_person_id在哪里 {?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 .{选择 ?other_person_id在哪里 {?place_of_birth_id fb:location.location.people_born_here ?other_person_id .}限制 1}过滤器(langMatches(lang(?place_of_birth),en"))}限制 3

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

解决方案

您可以对子查询使用限制

您可以在子查询中使用限制.举个例子:

select ?x ?y where {值 ?x { 1 2 3 4 }{选择 ?y 在哪里 {值 ?y { 5 6 7 8 }}限制 2}}限制 5

---------|× |是 |==========|1 |5 ||1 |6 ||2 |5 ||2 |6 ||3 |5 |---------

如您所见,您从子查询中获得了两个值(5 和 6),这些值与来自外部查询的绑定相结合,从中我们总共获得了 5 行(由于限制).

子查询最内层先求值

但是,请记住,子查询是从最内层到最外层进行评估的.这意味着在您的查询中,

select ?person_id ?place_of_birth ?other_person_id在哪里 {?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 .{选择 ?other_person_id在哪里 {?place_of_birth_id fb:location.location.people_born_here ?other_person_id .}限制 1}过滤器(langMatches(lang(?place_of_birth),en"))}限制 3

您正在为

找到一个匹配项

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

并将?other_person_id 绑定out 传递到外部查询中.不过,外部查询的其余部分不使用 ?other_person_id,因此它实际上对结果没有任何影响.

该怎么做

如果你只需要一个人

<块引用>

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

从概念上讲,您可以将其视为挑选一个人,找到他们的出生地,然后从出生在那个地方的人中再抽样一个人.您实际上也可以这样编写查询:

select ?person_id ?place_of_birth (sample(?other_person_idx) as ?other_person_id)在哪里 {?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 .过滤器(langMatches(lang(?place_of_birth),en"))?place_of_birth_id fb:location.location.people_born_here ?other_person_idx .过滤器 ( ?other_person_idx != ?person_id )}按 ?person_id ?place_of_birth 分组

如果您需要多个

如果您需要为每个结果提供多个​​其他结果",这是一个棘手得多的问题.这就是 带有限制的 sparql 中的嵌套查询 中的问题.如何限制 SPARQL 解决方案组的大小? 可用于此.

I am developing a java application that uses ARQ to execute SPARQL queries using a Fuseki endpoint over TDB.

The application needs a query that returns the place of birth of each person and other person that was born in the same place.

To start, I wrote this SPARQL query that returns person_ids and the place of birth of each person.

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 |
----------------------------------

After that, I added a subquery (https://jena.apache.org/documentation/query/sub-select.html) adding other person who was born there, but I get more than one person related and I only need one.

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     |
---------------------------------------------------

I have tried to add a LIMIT 1 subquery but it seems that does not work ( the query is executed but never ends )

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

Is there a way to return only one result in the subquery, or can I not do that using SPARQL.

解决方案

You can use limits with subqueries

You can use limits in subqueries. Here's an example:

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 |
---------

As you can see, you get two values from the subquery (5 and 6), and these are combined with the bindings from the outer query, from which we get five rows in total (because of the limit).

Subqueries are evaluated innermost first

However, keep in mind that subqueries are evaluated from the innermost first, to the outermost. That means that in your query,

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

you are finding one match for

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

and passing the ?other_person_id binding out into the outer query. The rest of the outer query doesn't use ?other_person_id, though, so it doesn't really have any effect on the results.

What to do instead

If you need only one other person

The application needs a query that returns the place of birth of each person and other person that was born in the same place.

Conceptually, you could look at this as picking a person, finding their place of birth, and sampling one more person from the people born in that place. You can actually write the query like that, too:

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

This is a much trickier problem if you need more than one "other result" for each result. That's the problem in Nested queries in sparql with limits. There's an approach in How to limit SPARQL solution group size? that can be used for this.

这篇关于SPARQL 使用带限制的子查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆