SPARQL cannot query "is of" relationship - sparql

I am querying some features like:
PREFIX dbo: <http://dbpedia.org/ontology/>
select ?field where {
dbpedia:Jeffrey_Karp dbo:field ?field
}
This return the content correctly. But if I query some feature in the form "is ** of", the query will return null, though the field exists. Here is the query:
select ?studentof where {
dbpedia:Jeffrey_Karp dbo:notableStudent ?studentof
}

Related

How to get a simple inferencing example to work

I might have understood something wrong, so bear with me.
I created a repository called 'reasoning' of type OWL2-RL (tried some other types already too).
I created a rule as follows:
prefix sys: <http://www.ontotext.com/owlim/system#>
INSERT DATA {
<_:pets> sys:addRuleset
'''Prefices { ex : <http://www.example.com#> }
Axioms {}
Rules
{
Id: custom
a <ex:hasPet> b
------------------------------------
b <ex:hasOwner> a
}'''
}
I insert some triples as follows:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ex: <http://www.example.com#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
INSERT DATA {
<ex:hasPet> a <owl:ObjectProperty>;
<rdfs:domain> <ex:Human>;
<rdfs:range> <ex:Pet>.
<ex:someHuman> <ex:hasPet> <ex:somePet>.
}
Consequently I set my rule as default as follows :
PREFIX sys: <http://www.ontotext.com/owlim/system#>
INSERT DATA {
_:b sys:defaultRuleset "pets"
}
I expect the following query
PREFIX ex: <http://www.example.com#>
select * where {
<ex:somePet> ?p ?o .
} limit 100
to return the following inferred triple
<ex:somePet> <ex:hasOwner> <ex:someHuman>
but unfortunately no inferred triples are present in the repository.
Could you please help me? Having a working example with the different steps to take will help me get rules to work in my application.
Thanks in advance!
Kind regards
There are multiple issues, first IRIs, within the Prefixes section of the ruleset must be written without angle brackets, e.g. use ex : http://www.example.com# instead ...
also your data and sample query do not make use of the prefix ex but are absolute IRIs, e.g. instead of
INSERT DATA {
<ex:hasPet> a <owl:ObjectProperty>;
<rdfs:domain> <ex:Human>;
<rdfs:range> <ex:Pet>.
<ex:someHuman> <ex:hasPet> <ex:somePet>.
}
rewrite to
INSERT DATA {
ex:hasPet a owl:ObjectProperty;
rdfs:domain ex:Human;
rdfs:range ex:Pet.
ex:someHuman ex:hasPet ex:somePet.
}

SPARQL: Conditional INSERT

I'm trying to create a SPARQL statement that inserts some triples only if a certain pattern isn't yet in the graph.
PREFIX ssb: <ssb:ontology:>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
INSERT {
<ssb:message/some=> rdf:type ssb:Message;
ssb:seq 7;
ssb:raw "some text";
ssb:author 1.
} WHERE {
FILTER NOT EXISTS {
[] ssb:seq 7; ssb:author 1
}
}
Unfortunately, this seems to create the new triples even if a resource with that ssb:seq and ssb:author already exist, tried the with quadstorejs and with oxigraph.
Any suggestion on how to perform such a conditional insert? The goal is that I don't end up with several resources having the same sequence number and author.
I believe your first attempt is correct and it looks like a bug in the systems that you tried.
The algebra for
FILTER NOT EXISTS {
[] ssb:seq 7; ssb:author 1
}
is the FILTER directly on top of Singleton and it must return a single (empty) solution when the [] ssb:seq 7; ssb:author 1 does not match data. Since there're no variables in your INSERT template, data should be inserted.
The version with OPTIONAL isn't much different, there's an implicit {} before the OPTIONAL, and it's the same Singleton.
I just tried a CONSTRUCT version of your 1st query with Stardog and it worked as expected.
I found a solution that seems to work:
PREFIX ssb: <ssb:ontology:>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
INSERT {
<ssb:message/some=> rdf:type ssb:Message;
ssb:seq 7;
ssb:raw "some text";
ssb:author 1.
} WHERE {
OPTIONAL {?x ssb:seq 7; ssb:author 1.}
FILTER (!BOUND(?x))
}
Not sure exactly why, though. I mean the WHERE-Clause either matches nothing because the pattern isn't there or because it is filtered out when it exists.

SPARQL: Inverse result on boolean query

I am trying to have SPARQL return 'false' if a set of triples exist in an RDF database. I'm able to return 'true' with an ASK query.
ASK WHERE { ?subjID rdf:type pref:Person. }
As described here, I tried adding NOT EXISTS { } inside of the WHERE, but this results in an error.
ASK WHERE { NOT EXISTS { ?subjID rdf:type pref:Person. } }
The documentation that I linked doesn't describe this but you must put FILTER in front of NOT EXISTS.
ASK WHERE { FILTER NOT EXISTS { ?subjID rdf:type pref:Person. } }

Best approach to create URIs with Sparql (like auto increment)

I am currently writing a service which creates new items (data) by user input. To save these items in a RDF Graph Store (currently using Sesame via Sparql 1.1), I need to add a subject URI to the data. My approach is to use a number that is incremented for each new item. So e.g.:
<http://example.org/item/15> dct:title "Example Title" .
<http://example.org/item/16> dct:title "Other Item" .
What's the best approach to get an incremented number for new items (like auto incement in MySQL/MongoDB) via Sparql? Or to issue some data and the endpoint autmatically creates a URI by a template (like done for blank nodes).
But I don't want to use blank nodes as subjects for these items.
Is there a better solution than using an incremented number? My users don't care about the the URI.... and I don't want to handle collisions like created by hashing the data and using the hash as part of the subject.
If you maintain a designated counter during updates, then something along these lines will do it,
fisrt insert a counter into your dataset
insert data {
graph <urn:counters> {<urn:Example> <urn:count> 1 }
}
then a typical update should looks like:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
delete {
#remove the old value of the counter
graph <urn:counters> {<urn:Example> <urn:count> ?old}
}
insert {
#update the new value of the counter
graph <urn:counters> {<urn:Example> <urn:count> ?new}
# add your new data using the constructed IRI
GRAPH <http://example.com> {
?id dct:title "Example Title" ;
a <http://example.org/ontology/Example> .
} .
} where {
# retrieve the counter
graph <urn:counters> {<urn:Example> <urn:count> ?old}
# compute the new value
bind(?old+1 as ?new)
#construct the IRI
bind(IRI(concat("http://example.org/item/", str(?old))) as ?id)
}
Assuming the class of your items is http://example.org/ontology/Example, the query becomes the following. Note: items must be inserted one by one, as only one new URI is computed at each transaction.
PREFIX dct: <http://purl.org/dc/terms/>
INSERT {
GRAPH <http://example.com> {
?id dct:title "Example Title" ;
a <http://example.org/ontology/Example> .
} .
} WHERE {
SELECT ?id WHERE {
{
SELECT (count(*) AS ?c) WHERE {
GRAPH <http://example.com> { ?s a <http://example.org/ontology/Example> }
}
}
BIND(IRI(CONCAT("http://example.org/item/", STR(?c))) AS ?id)
}
}
(Tested with GraphDB 8.4.0 using RDF4J 2.2.2)
You said you are open to other options than an auto-incremented number. One good alternative is to use UUIDs.
If you don't care at all what the URI looks like, you can use the UUID function:
INSERT {
?uri dct:title "Example Title"
}
WHERE {
BIND (UUID() AS ?uri)
}
This will generate URIs like <urn:uuid:b9302fb5-642e-4d3b-af19-29a8f6d894c9>.
If you'd rather have HTTP URIs in your own namespace, you can use strUUID:
INSERT {
?uri dct:title "Example Title"
}
WHERE {
BIND (IRI(CONCAT("http://example.org/item/", strUUID())) AS ?uri)
}
This will generate URIs like http://example.org/item/73cd4307-8a99-4691-a608-b5bda64fb6c1.
UUIDs are pretty good. Collision risk is negligible. The functions are part of the SPARQL standard. The only downside really is that they are long and ugly.

Exact match of variable string in SPARQL Wikidata Query Service

Exact match of variable string in SPARQL Wikidata Query Service at https://query.wikidata.org does not give the the results I expected.
I was expecting I could do:
SELECT * {
hint:Query hint:optimizer "None" .
{ SELECT DISTINCT (xsd:string(?author_name_) AS ?author_name) { wd:Q5565155 skos:altLabel ?author_name_ . } }
?work wdt:P2093 ?author_name .
}
But I get no returned results from the Wikidata Query Service:
However, if I use the "=" comparison, I can match the strings:
SELECT * {
hint:Query hint:optimizer "None" .
{ SELECT DISTINCT (xsd:string(?author_name_) AS ?author_name) { wd:Q5565155 skos:altLabel ?author_name_ . } }
?work wdt:P50 wd:Q5565155 .
?work wdt:P2093 ?author_name__ .
FILTER (?author_name = ?author_name__)
}
With the current data in Wikidata, I get five rows returned in this query.
Another way to get this data is by using a BIND:
SELECT * {
BIND("Knudsen GM" AS ?author_name)
?work wdt:P2093 ?author_name .
}
I suppose there might be something wrong with the casting as this does not return anything:
SELECT * {
BIND(xsd:string("Knudsen GM") AS ?author_name)
?work wdt:P2093 ?author_name .
}
Combinations with xsd:string changed to STR or no conversion at all in the original query do neither yield result rows.