SPARQL BIND function Syntax error - sparql

Hi Guys am trying run a SPARQL query on Virtuoso version 6.1.x. Here is the query:
SPARQL PREFIX fns: <NAMESPACE> SELECT ?birth ?death ?age ?value ?typeId FROM <http://freebaseInc5>
WHERE { fns:m.030pk7c fns:people.person.date_of_birth ?birth; fns:people.deceased_person.date_of_death ?death; BIND(year(?death)-year(?birth) as ?age ) .
OPTIONAL {?mid fns:common.topic.notable_types ?type . ?type fns:type.object.id ?typeId } .
OPTIONAL {?mid fns:type.object.name ?value FILTER langMatches(lang(?value), "en") }}
I am getting the error complaining about the syntax:
> SQLState: 37000
Message: SQ074: Line 4: SP030: SPARQL compiler, line 2: syntax error at 'BIND' before '('
SPARQL PREFIX fns: <NAMESPACE> SELECT ?birth ?death ?age ?value ?typeId FROM <NAMESPACE>
WHERE { fns:m.030pk7c fns:people.person.date_of_birth ?birth; fns:people.deceased_person.date_of_death ?death; BIND(year(?death)-year(?birth) as ?age ) .
OPTIONAL {?mid fns:common.topic.notable_types ?type . ?type fns:type.object.id ?typeId } .
OPTIONAL {?mid fns:type.object.name ?value FILTER langMatches(lang(?value), "en") }}
I don't see what the error is; what am I missing?

It's actually legal SPARQL…
Here's your query, with improved formatting, and with the "SPARQL" removed from the beginning, but no other changes:
PREFIX fns: <NAMESPACE>
SELECT ?birth ?death ?age ?value ?typeId
FROM <http://freebaseInc5>
WHERE {
fns:m.030pk7c fns:people.person.date_of_birth ?birth ;
fns:people.deceased_person.date_of_death ?death ;
BIND(year(?death)-year(?birth) as ?age ) .
OPTIONAL {
?mid fns:common.topic.notable_types ?type .
?type fns:type.object.id ?typeId
} .
OPTIONAL {
?mid fns:type.object.name ?value
FILTER langMatches(lang(?value), "en")
}
}
According to sparql.org's query validator, the query is well formed (which actually suprised me, given the ; after ?death, but I guess it's OK after all).
…but Virtuoso doesn't like it.
But if I try to run this on DBpedia's endpoint, which runs Virtuoso, (along with a limit 1, just to make sure it's not actually going to use much in the way of resources), I see the error you're talking about:
Virtuoso 37000 Error SP030: SPARQL compiler, line 10: syntax error at 'BIND' before '('
SPARQL query:
define sql:big-data-const 0
#output-format:text/html
define sql:signal-void-variables 1 define input:default-graph-uri <http://dbpedia.org> PREFIX fns: <NAMESPACE>
SELECT ?birth ?death ?age ?value ?typeId
FROM <http://freebaseInc5>
WHERE {
fns:m.030pk7c fns:people.person.date_of_birth ?birth ;
fns:people.deceased_person.date_of_death ?death ;
BIND(year(?death)-year(?birth) as ?age ) .
OPTIONAL {
?mid fns:common.topic.notable_types ?type .
?type fns:type.object.id ?typeId
} .
OPTIONAL {
?mid fns:type.object.name ?value
FILTER langMatches(lang(?value), "en")
}
}
LIMIT 1
However, if you change the ; after ?death to ., or remove it completely, the query is accepted without any problem.

Related

Make a UNION return a single result in SPARQL

I am trying to query for the sh:description of a property shape, and if there is none, I want to follow the path to a property and get the rdfs:comment (Also for sh:name and rdfs:label). My data looks like the following:
ex:File
a owl:Class ;
a sh:NodeShape ;
sh:property ex:File-name ;
ex:File-name
a sh:PropertyShape ;
sh:path ex:filename ;
sh:datatype xsd:string ;
sh:description "The name of the file" ;
sh:maxCount 1 ;
ex:filename
a rdf:Property ;
rdfs:label "Filename" ;
rdfs:comment "The file name" ;
.
I have the query below, but it returns two results. How can I modify it to only return a single result (preferring sh:description over rdfs:comment)?
PREFIX : <http://www.example.org/#>
PREFIX sh: <http://www.w3.org/ns/shacl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?propertyShape ?property ?name ?description where {
:File sh:property ?propertyShape .
?propertyShape sh:path ?property .
{ ?propertyShape sh:name ?name } UNION { ?property rdfs:label ?name } .
{ ?propertyShape sh:description ?description } UNION { ?property rdfs:comment ?description } .
The above returns something like this:
propertyShape
property
name
description
:File-name
ex:filename
"Filename"
"The name of the file"
:File-name
ex:filename
"Filename"
"The file name"
I would like for it to return something like:
propertyShape
property
name
description
:File-name
ex:filename
"Filename"
"The name of the file"
You should be able to use a sequence of OPTIONAL blocks to do this:
SELECT ?propertyShape ?property ?name ?description WHERE {
:File sh:property ?propertyShape .
?propertyShape sh:path ?property .
OPTIONAL { ?propertyShape sh:name ?name }
OPTIONAL { ?property rdfs:label ?name }
OPTIONAL { ?propertyShape sh:description ?description }
OPTIONAL { ?property rdfs:comment ?description }
}
You'll still have to think about cases where there are multiple names/descriptions per property (this isn't guaranteed to return just a single result), but it should give you the "preferring sh:description over rdfs:comment" behavior.
Can't you just use path expressions such as
...
?propertyShape sh:name|(sh:path/rdfs:label) ?name .
?propertyShape sh:description|(sh:path/rdfs:comment) ?description .

Sparql UNION returns Virtuoso 37000 Error SP031

I have the query shown below:
SELECT DISTINCT ?dataset ?title WHERE {
?dataset a dcat:Dataset ;
dcterms:title ?title ;
dcterms:description ?description .
{ ?dataset dcterms:title ?title .
?title bif:contains "'keyword_1'" }
UNION
{ ?dataset dcterms:description ?description .
?description bif:contains "'keyword_1'" }
{ ?dataset dcterms:title ?title .
?title bif:contains "'keyword_2'" }
UNION
{ ?dataset dcterms:description ?description .
?description bif:contains "'keyword_2'" }
}
Semantically, this query is supposed to return all datasets which have "keyword_1" in either their "title" or "description" (this is the first UNION clause) and "keyword_2" in either their "title" or "description" (second UNION clause). The intent is to intersect these two UNION clauses together, that is, getting only only those datasets which fulfill both clauses.
This validator tells me that the query is syntactically correct. However, when sending the query to Virtuoso, the following error is returned:
Virtuoso 37000 Error SP031: SPARQL compiler: Internal error: sparp_find_triple_with_var_obj_of_freetext(): lost connection between triple pattern and an ft predicate
SPARQL query:
define sql:big-data-const 0
output-format:text/html<br>
define sql:signal-void-variables 1
Do you have an idea whats going on? I don't get what Virtuoso is trying to tell me when stating "lost connection between triple pattern and an ft predicate"...
Thanks in advance!
Maybe a bug in the query executor or optimizer. The Virtuoso experts like TallTed know better and will give you support.
I can at least reproduce this on e.g. https://www.europeandataportal.eu/sparql which runs on Virtuoso version 07.20.3230 on Linux (x86_64-unknown-linux-gnu), Single Server Edition.
But, more important: your query looks way too complex as you could use a FILTER with logical || in combination with && - at least that's what I thought.
Unfortunately, it fails with an error
Virtuoso 37000 Error SP031: SPARQL compiler: No suitable triple pattern is found for a variable $description in special predicate bif:contains() at line 7 of query
and neither
SELECT DISTINCT ?dataset ?title WHERE {
?dataset a dcat:Dataset ;
dcterms:title ?title ;
dcterms:description ?description .
filter( (bif:contains(?title, "'keyword_1'") || bif:contains(?description,"'keyword_1'"))
&&
(bif:contains(?title, "'keyword_2'") || bif:contains(?description,"'keyword_2'"))
)
}
nor
SELECT DISTINCT ?dataset ?title WHERE {
?dataset a dcat:Dataset ;
dcterms:title ?title ;
dcterms:description ?description .
filter(bif:contains(?title, "'keyword_1'") || bif:contains(?description,"'keyword_1'"))
filter(bif:contains(?title, "'keyword_2'") || bif:contains(?description,"'keyword_2'"))
}
do work as I'd expect.
(Verbose) workaround using subqueries:
SELECT DISTINCT ?dataset ?title WHERE {
{
select ?dataset ?title {
?dataset a dcat:Dataset ;
dcterms:title ?title ;
dcterms:description ?description .
filter( bif:contains(?title, "'keyword_1'") || bif:contains(?description,"'keyword_1'"))
}
}
{
select ?dataset ?title {
?dataset a dcat:Dataset ;
dcterms:title ?title ;
dcterms:description ?description .
filter( bif:contains(?title, "'keyword_2'") || bif:contains(?description,"'keyword_2'"))
}
}
}

How to add conditions to a query

I would like to add a condition to a query, so that, if a result is empty, it fills it with a result of another query.
For example : If a owl:Class has no "skos:definition", I would like to replace it by a "rdfs:comment"
Is this possible ?
Thank you !
COALESCE is can help, especially as you get more choices from skos:prefLabel, skos:altLabel and more.
OPTIONAL { ?property rdfs:label ?label }
OPTIONAL { ?property skos:definition ?definition .}
# ... other ways to choose ?comment ...
BIND ( COALESCE(?definition, ?label, "Unknown") AS ?comment )
COALESCE allows expressions (unlike BOUND)
https://www.w3.org/TR/sparql11-query/#func-coalesce
I found something with BIND (IF(BOUND(...) ..., ...) AS ...) statement.
SELECT DISTINCT ?type ?property ?comment ?propertyType ?domain
WHERE {
?property rens:hasAttributeType ?propertyType .
?property rens:hasForDomain ?domain .
?property rdf:type ?type .
?property rdfs:label ?label .
OPTIONAL {?property skos:definition ?definition .}
BIND(IF(BOUND(?definition), ?definition, ?label) AS ?comment) .
}
Is this the better way ?

Aggregate properties

I'm developing my own Fuseki endpoint from some DBpedia data.
I'm in doubt on how to aggregate properties related to a single resource.
SELECT ?name ?website ?abstract ?genre ?image
WHERE{
VALUES ?s {<http://dbpedia.org/resource/Attack_Attack!>}
?s foaf:name ?name ;
dbo:abstract ?abstract .
OPTIONAL { ?s dbo:genre ?genre } .
OPTIONAL { ?s dbp:website ?website } .
OPTIONAL { ?s dbo:image ?image } .
FILTER LANGMATCHES(LANG(?abstract ), "en")
}
SPARQL endpoint: http://dbpedia.org/sparql/
This query returns 2 matching results. They are different just for the dbo:genre value. There is a way I can query the knowledge base and retrieving a single result with a list of genres?
#chrisis's query works well on the DBpedia SPARQL Endpoint, which is based on Virtuoso.
However, if you are using Jena Fuseki, you should use more conformant syntax:
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
SELECT
?name
(SAMPLE(?website) AS ?sample_website)
(SAMPLE(?abstract) AS ?sample_abstract)
(SAMPLE(?image) AS ?sample_image)
(GROUP_CONCAT(?genre; separator=', ') AS ?genres)
WHERE {
VALUES (?s) {(<http://dbpedia.org/resource/Attack_Attack!>)}
?s foaf:name ?name ;
dbo:abstract ?abstract .
OPTIONAL { ?s dbo:genre ?genre } .
OPTIONAL { ?s dbp:website ?website } .
OPTIONAL { ?s dbo:image ?image} .
FILTER LANGMATCHES(LANG(?abstract ), "en")
} GROUP BY ?name
The differences from the #chrisis's query are:
Since GROUP_CONCAT is an aggregation function, it might be used with GROUP BY only;
Since GROUP BY is used, all non-grouping variables should be aggregated (e.g. via SAMPLE);
GROUP_CONCAT syntax is slightly different.
In Fuseki, these AS in the projection are in fact superfluous: see this question and comments.
Yes, the GROUP_CONCAT() function is what you want.
SELECT ?name ?website ?abstract (GROUP_CONCAT(?genre,',') AS ?genres) ?image
WHERE{
<http://dbpedia.org/resource/Attack_Attack!> a dbo:Band ;
foaf:name ?name;
dbo:abstract ?abstract .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbo:genre ?genre } .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbp:website ?website} .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbo:image ?image} .
FILTER LANGMATCHES(LANG(?abstract ), "en")
}

querying dbpedia sparql for more results

I want to obtain some data from dbpedia.
I have entities urls and want to get some information about localization.
Now i call query like this:
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT DISTINCT * WHERE
{
<{0}> rdfs:label ?label .
OPTIONAL {
<{0}> geo:lat ?lat ;
geo:long ?long .
} .
OPTIONAL {
<{0}> dbo:Country ?dboCountry
} .
OPTIONAL {
<{0}> dbpedia-owl:country ?dbpediaContry .
?dbpediaContry dbpprop:cctld ?ccTLD
}.
OPTIONAL {
<{0}> dbpprop:country ?dbpropContry
}
FILTER ( lang(?label) = "en" )
}
for each url (replace {0} with url).
But I would like to optimize it and get result for more entities in one query.
Also is it possible to not set url in each line?
Regards
Piotr
Hmm, it looks I already have found an answer for both questions.
Do you know this(http://en.wikipedia.org/wiki/Rubber_duck_debugging)
Solution is:
SELECT DISTINCT *
WHERE {
?uri rdfs:label ?label .
OPTIONAL { ?uri geo:lat ?lat .
?uri geo:long ?long} .
FILTER (?uri IN ({0}, {1}, ...) )
}
Maybe it will be helpful for somebody else?
Or maybe someone knows better solution?