SPARQL using a subquery with a constraint

I am developing a Java application that uses ARQ to execute SPARQL queries using the Fuseki endpoint using TDB protocol.

The application needs a query that returns the birthplace of each person and another person born in the same place.

To get started, I wrote this SPARQL query, which returns person_ids and the birthplace 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 another person who was born there, but I get more than one person 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 tried to add the LIMIT 1 subquery, but it seems that it does not work (the request 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 a subquery, or can I not do this using SPARQL.

+8
source share
1 answer

You can use limits with subqueries

You can use restrictions in subqueries. Here is 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 they are combined with the bindings from the external query, from which we get only five rows (due to the restriction).

Subqueries are first evaluated first

However, keep in mind that subqueries are evaluated from the most internal to the most external. This means that in your request

 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 will find one match for

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

and transfers ? other_person_id bindings to an external request. Does the rest of the external query not use ? Other_person_id , so in fact this has no effect on the results.

What to do instead

If you only need one person

The application needs a query that returns the birthplace of each person and another person born in the same place.

Conceptually, you could look at this, how to recruit a person, find a place of birth and select another person from people born in this place. You can also write this query:

 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 more complex problem if more than one β€œother result” is required for each result. This is a problem in Nested queries in sparql with restrictions . Q How to limit the size of a SPARQL solution group? which can be used for this.

+16
source

Source: https://habr.com/ru/post/978513/


All Articles