I'm having trouble writing a correct Stardog rule. As I haven't found a way to validate the syntax of the rule, I don't now if it's a syntax or a logical error. Eitherway, the rule doesn't seem to be triggered when reasoning is enabled (reasoning=SL in version 2, reasoning=true in version 3).
#prefix : <http://www.example.org/rules#> .
#prefix rule: <tag:stardog:api:rule:> .
#base <http://www.example.org/rules#> .
[] a rule:SPARQLRule ;
rule:content """
PREFIX : <http://www.example.org/rules#>
PREFIX draft: <http://our/prefix#>
IF {
?x a draft:Obs; draft:has_code ?code .
?z a <http://www.w3.org/ns/sparql#UUID> . // OR: BIND (UUID() AS ?z)
}
THEN {
?z a draft:Code .
?x draft:has_code ?z .
}
""" .
I'm trying to trigger the rule with the following SPARQL query:
PREFIX : <http://our/prefix>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?code
FROM <tag:stardog:api:context:default>
FROM <http://our/graph>
WHERE {
?s rdf:type :Obs .
?obs :has_code ?code .
}
This is likely due to the cyclic nature of the rule. You're inferring :has_code which will in turn be used to fire the rule again, and again, and so forth.
This is a bit easier to visualize when you consider how rules with more than one atom in the header a broken up.
Related
In a certain knowledge graph there is a large number of individuals that need
to be assigned a literal token of the type xsd:token. It is not practical to
do so manually, therefore I am trying with an INSERT instruction. However, I
can't find a way to assign the desired literal type in that kind of query.
Consider in first place this basic example knowledge graph:
#prefix : <http://my.example.web/> .
#prefix foaf: <http://xmlns.com/foaf/0.1/> .
:1 a foaf:Person ;
foaf:name "Jane Doe" .
:2 a foaf:Person ;
foaf:name "John Smith" .
The exercise would be to add a token created by removing the blank spaces from
the foaf:name literal. For the :1 this would translate into the addition of the triple:
:1 dcterms:identifier "JaneDoe"^^xsd:token .
With a SELECT query I can archive it the following
way:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT STRDT(?token, xsd:token)
WHERE {
GRAPH <http://my.example.web/> {
?s foaf:name ?name .
BIND(REPLACE(STR(?name)," ","") AS ?token) .
}
}
Which produces the result:
LONG VARCHAR
_______________________________________________________________________________
JaneDoe
JohnSmith
2 Rows. -- 54 msec.
Now using the same formulation, but with an INSERT query:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
INSERT
{
GRAPH <http://my.example.web/> {
?s dcterms:identifier STRDT(?token, xsd:token) .
}
}
WHERE {
GRAPH <http://my.example.web/> {
?s foaf:name ?name .
BIND(REPLACE(STR(?name)," ","") AS ?token) .
}
}
An error is the result:
*** Error 37000: [Virtuoso Driver][Virtuoso Server]SQ074: Line 17 (line 17 of "(console)"): SP030: SPARQL compiler, line 9: syntax error at 'STRDT' before '('
In essence I need a way to apply the STRDT function to the
object of a triple inside the INSERT clause. Or any other alternative mechanism allowing to set a literal type in this kind of query.
Both your queries are invalid:
SELECT STRDT(?token, xsd:token)
According to the SelectClause production, an expression must be followed by AS to give it a variable binding. In essence, you have to use the same syntax you would have used after BIND (you also need parentheses around it). As for why Virtuoso accepts this, well Virtuoso does not strictly follow all of SPARQL ‒ it also allows , between the variables in SELECT, has the DEFINE clause, and allows undeclared prefixes if they are recognized by the store.
This is valid:
SELECT (STRDT(?token, xsd:token) AS ?tokenTyped)
or modify the BIND:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?token
WHERE {
GRAPH <http://my.example.web/> {
?s foaf:name ?name .
BIND(STRDT(REPLACE(STR(?name)," ",""), xsd:token) AS ?token) .
}
}
This seems the cleanest to me.
Likewise, for the second query, you cannot have an expression as an object of a triple (or any position for that matter), see the Object production. Using a variable is the best the syntax allows you to do (while it would certainly be nice to be able to use expressions as you wanted):
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
INSERT
{
GRAPH <http://my.example.web/> {
?s dcterms:identifier ?token .
}
}
WHERE {
GRAPH <http://my.example.web/> {
?s foaf:name ?name .
BIND(STRDT(REPLACE(STR(?name)," ",""), xsd:token) AS ?token) .
}
}
I have tested it and it should work on OpenLink Virtuoso version 07.20.3231. If you have issues with this, perhaps the Virtuoso instance needs to be updated, or refer to GitHub.
I have some working code for getting all the ancestors of a term in a hierarchy.
Following:
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX skos-xl: <http://www.w3.org/2008/05/skos-xl#>
PREFIX rdf: <http://www.w3.org/2000/01/rdf-schema#>
select ?grandparentliteralform (count(?parent) as ?distance)
{ ?iri skos:broader+ ?parent .
?parent skos:broader* ?grandparent .
?grandparent skos-xl:prefLabel ?grandparentlabel .
?grandparentlabel skos-xl:literalForm ?grandparentliteralform .
}
group by ?grandparent
order by DESC(?distance)
It breaks when an IRI's broader predicate is a subproperty (?p rdf:subPropertyOf skos:broader)
So right now I am doing this to capture all the subproperty predicates:
select ?grandparentliteralform (count(?parent) as ?distance)
{ ?iri ?p ?parent .
?parent skos:broader* ?grandparent .
?grandparent skos-xl:prefLabel ?grandparentlabel .
?grandparentlabel skos-xl:literalForm ?grandparentliteralform .
?p rdf:subPropertyOf skos:broader .
}
group by ?grandparent
order by DESC(?distance)
What i would really like to do is :
select ?grandparentliteralform (count(?parent) as ?distance)
{ ?iri ?p+ ?parent .
?parent ?p* ?grandparent .
?grandparent skos-xl:prefLabel ?grandparentlabel .
?grandparentlabel skos-xl:literalForm ?grandparentliteralform .
?p rdf:subPropertyOf skos:broader .
}
group by ?grandparent
order by DESC(?distance)
but using ?p+ or ?p* throws an error.
Unexpected token syntax error, unexpected <variable>, expecting <decimal literal> or <double literal> or <integer literal>
How can I use */+ with variables?
You can't. As the Property Paths section of the SPARQL 1.1 spec states:
The ends of the path may be RDF terms or variables. Variables can not be used as part of the path itself, only the ends.
You could potentially use alternatives to capture this:
?parent (skos:broader|your:alternative)* ?grandparent
Exact form will need to reflect your data structure and whether you want to allow mixes of skos:broader and your alternative (which my example allows). You can move the * operator inside the brackets and add it to each alternative if you want pure chains of specific properties.
Is it possible to execute SPARQL construct while adding information outside the scope of query? e.g., I want to execute SPARQL construct while defining enumeration information like this:
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
construct {
?s a skos:Concept
?s ex:index <enumeration starting from 1 -- this is just a sample>
}
where {
?s a skos:Concept
}
is it possible to do something like that with pure SPARQL? what are the alternatives?
* Additional Information *
Probably I am not explained my problem clearly, so basically I want to achieve the following (assuming that ex:index is a valid datatypeProperty):
== Initial RDF triples ==
#prefix skos:<http://www.w3.org/2004/02/skos/core#>
#prefix ex: <http://example.org/> .
ex:abc rdf:type skos:Concept .
ex:def rdf:type skos:Concept .
...
ex:endOfSample rdf:type skos:Concept .
== RDF triples after SPARQL Update execution ==
#prefix skos:<http://www.w3.org/2004/02/skos/core#>
#prefix ex: <http://example.org/> .
ex:abc rdf:type skos:Concept ;
ex:index 1 .
ex:def rdf:type skos:Concept ;
ex:index 2 .
...
ex:endOfSample rdf:type skos:Concept ;
ex:index <endOfSampleNumber> .
You can construct any valid RDF value in a CONSTRUCT. However the query will fail if any of the variables in the CONSTRUCT graph pattern is unbound after executing the WHERE graph. I.e. there can be no binding for ?p in your query and the CONSTRUCT will never execute.
This is an example that should get you started:
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
PREFIX ex:<http://example.org/construct#>
construct {
ex:someProp a owl:ObjectProperty .
?s ex:someProp (1 2 3)
}
where {
?s a skos:Concept
}
This will result in the construction of seven triples for the property value and the list structure.
The ex:someProp is added because there isn't a good object property in SKOS for ad-hoc lists. It would be best to define the property with some semantic meaning. Also note that while the {ex:someProp a owl:ObjectProperty} triple will be asserted for each match of {?s a skos:Concept}, it is the same triple, hence there will be only one in the end. The price is efficiency, so asserting the property outside of this query would be a better choice - it is included in the above query for the sake of example completeness.
I have an OWL file that includes a taxonomic hierarchy that I want to write a query where the answer includes each individual and its immediate taxonomic parent. Here's an example (the full query is rather messier).
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix rdf: <http:://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix : <urn:ex:> .
:fido rdf:type :Dog .
:Dog rdfs:subClassOf :Mammal .
:Mammal rdfs:subClassOf :Vertebrate .
:Vertebrate rdfs:subClassOf :Animal .
:fido :hasToy :bone
:kitty rdf:type :Cat .
:Cat rdfs:subClassOf :Mammal .
:kitty :hasToy :catnipMouse .
And this query does what I want.
prefix rdf: <http:://www.w3.org/1999/02/22-rdf-syntax-ns#> .
prefix : <urn:ex:> .
SELECT ?individual ?type
WHERE {
?individual :hasToy :bone .
?individual rdf:type ?type .
}
The problem is that I'd rather use a reasoned-over version of the OWL file, which unsurprisingly includes additional statements:
:fido rdf:type :Mammal .
:fido rdf:type :Vertebrate .
:fido rdf:type :Animal .
:kitty rdf:type :Mammal .
:kitty rdf:type :Vertebrate .
:kitty rdf:type :Animal .
And now the query results in additional answers about Fido being a Mammal, etc. I could just give up on using the reasoned version of the file, or, since the SPARQL queries are called from java, I could do a bunch of additional queries to find the least inclusive type that appears. My question is whether there is a reasonable pure SPARQL solution to only returning the Dog solution.
A generic solution is that you make sure you ask for the direct type only. A class C is the direct type of an instance X if:
X is of type C
there is no C' such that:
X is of type C'
C' is a subclass of C
C' is not equal to C
(that last condition is necessary, by the way, because in RDF/OWL, the subclass-relation is reflexive: every class is a subclass of itself)
In SPARQL, this becomes something like this:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <urn:ex:> .
SELECT ?individual ?type
WHERE {
?individual :hasToy :bone .
?individual a ?type .
FILTER NOT EXISTS { ?individual a ?other .
?other rdfs:subClassOf ?type .
FILTER(?other != ?type)
}
}
Depending on which API/triplestore/library you use to execute these queries, there may also be other, tool-specific solutions. For example, the Sesame API (disclosure: I am on the Sesame dev team) has the option to disable reasoning for the purpose of a single query:
TupleQuery query = conn.prepareTupleQuery(SPARQL, "SELECT ...");
query.setIncludeInferred(false);
TupleQueryResult result = query.evaluate();
Sesame also offers an optional additional inferencer (called the 'direct type inferencer') which introduces additional 'virtual' properties you can query, such as sesame:directType, sesame:directSubClassOf, etc. Other tools will undoubtedly have similar options.
I have create an endpoint SPAQL on OpenLink Virtuoso.
All work well, but i have to access on the data in a Container, in particular a rdf:Seq.
I have a Seq like this:
<myrdf:has_stoptimes>
<rdf:Seq rdf:about="http://test.com/343">
<rdf:li>
<myrdf:StopTime rdf:about="http://test.com/StopTime/434">
...
</ns0:StopTime>
</rdf:li>
<rdf:li>
<myrdf:StopTime rdf:about="http://test.com/StopTime/435">
...
</ns0:StopTime>
</rdf:li>
</rdf:Seq>
Now i see that to access data in a container i can use rdfs:member or FILTER (strstarts(str(?prop), str(rdf:_)) how is explained here
But for my project i have to adopt the first solution because i'm working with Silk and i will use the code syntax like ?a/myrdf:has_stoptimes/rdfs:member without use of "complex" filter.
I have tried to follow this guide but querying the endpoint nothing work how i hoped.
So my question is: how can i query ?a/myrdf:has_stoptimes/rdfs:member on a Virtuoso endpoint SPARQL?Which inference rule i have to add in endpoint SPARQL?
Thank you in advance
UPDATE
I have created the following inference rules in Virtuoso:
ttlp (' #prefix rdfs: .
#prefix rdf: .
rdfs:Container rdf:type rdfs:Class ; rdfs:subClassOf rdfs:Resource .
rdfs:ContainerMembershipProperty a rdfs:Class ; rdfs:subClassOf rdf:Property .
rdf:Seq rdf:type rdfs:Class ; rdfs:subClassOf rdfs:Container .
rdfs:member rdf:type rdf:Property ; rdfs:domain rdfs:Resource ; rdfs:range rdfs:Resource .
', '', 'http://localhost:8890/schema/test') ;
Nothing work querying the SPARQL endpoint like:
define input:inference "http://localhost:8890/schema/property_rules1"
SELECT *
FROM
WHERE {?sep a rdf:Seq.
?seq rdfs:member ?p}
After i tried adding the follow line to the ttl file: rdf:_1 rdfs:subPropertyOf rdfs:member . In this way it work but obviously the results are only for the first element of the container. So is very unconvenient add a line for all of rdf:_n, and i think this is only a temporary solution, it is not correct.
I have tried to add an RDF dump on SILK 2.6.1, and on the section SPARQL of the data source if i run the query:
SELECT *
FROM
WHERE {?sep a rdf:Seq.
?seq rdfs:member ?p}
I obtain the correct result, without specify any inference rules. So i think that in this functionality of SILK there is something that i’m missing in my endpoint SPARQL or am i saying nonsense things?
You can't use variables in property paths, so you can't actually do
?x ?a/has_stoptimes/rdfs:member ?y
Instead, you have to use another variable or blank node in between:
?x ?a ?z . ?z has_stoptimes/rdfs:member ?y
?x ?a [ has_stoptimes/rdfs:member ?y ] .