Ok lets assume I have 5 datatype properties with integers as values. These properties are asserted to individuals belonging to class "WWS". This class has like 4 individuals. But only some of the datatype properties exist in these individuals. How can I query the individuals of this class that satisfy like the value 5. I want the variable to show only those individuals whose properties are satisfied, rest shouldnt appear.
I hope this is more clear!
Thank you!
Data:
datatype properties (range:integers): #greaterthantoc #lessthantoc #lowerlimtoc #upperlimtoc #equalstoc
individuals: #ww1, #ww2, #ww3 , #ww4 belong to class #WWS
#ww1 has #greaterthantoc "0"^^xsd:integer
#ww2 has #lessthantoc "5"^^xsd:integer
#ww3 has #greaterthantoc "5"^^xsd:integer
#ww4 has #lowerlimtoc "9"^^xsd:integer and #upperlimtoc "10"^^xsd:integer
Conditions for each property (filter?):
#greaterthantoc <= "a number"
#lessthantoc >= "a number"
#lowerlimtoc <= "a number" && #upperlimtoc >= "a number"
#equalstoc = "a number"
Results should be the WWS individuals who satisfy some of these conditions. For example when number is 4 then results should be WW1 and WW2
I suspect I need something like this for my case, but it still wont return results:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ww:<#>
SELECT ?str
WHERE {?str rdf:type ww:WWS .
OPTIONAL { ?str ww:greaterthantoc ?gr; ww:lessthantoc ?les ; ww:lowerlimtoc ?low ; ww:upperlimtoc ?up ; ww:equalstoc ?eq . }
FILTER ( ?les >= 3 || ?gr <= 3 || (?low <= 3 && ?up >=3) || ?eq = 3)
}
You haven't shown your data, and your queries change in odd ways (e.g., using a different URI for the ww:
prefix), so it's hard to say what any of the queries that you've provided you actually return. However, it is certainly possible to use more than one condition with ||
in a SPARQL filter.
Using the values
construct, we can provide some data in the query and see that a multi-way ||
works:
prefix : <http://stackoverflow.com/q/23561351/1281433/>
select ?s where {
values (?s ?gr ?les ?eq ?low ?up) {
(:s1 3 0 0 0 0)
(:s2 0 3 0 0 0)
(:s3 0 0 3 0 0)
(:s4 0 0 0 3 0)
(:s5 0 0 0 0 3)
(:s6 0 0 0 0 0)
(:s7 1 1 1 1 1)
}
filter ( ?eq > 2 || ?les > 2 || ?gr > 2 || ?low > 2 || ?up > 2 )
}
Note that the values associated with :s6
and :s7
don't have any values greater than two, so we don't expect to see them in the output. The rest each have a value that will make one of the disjuncts true. Here are the query results:
-------
| s |
=======
| :s1 |
| :s2 |
| :s3 |
| :s4 |
| :s5 |
-------
In the example above, as in the original version of the question, the constraint on each variable was the same. If that's the case, you can make this query shorter by using a disjunctive property path, or using values
. Using a disjunctive property path, you could write:
select ?s where {
?s :prop1|:prop2|:prop3|:prop4 ?value
filter ( ?value > 2 )
}
Using values, you could write:
select ?s where {
values ?prop { :prop1 :prop2 :prop3 :prop4 }
?s ?prop ?value
filter ( ?value > 2 )
}
Since you mentioned interaction with optional
, note that each of these has the advantage that ?s
doesn't have to have values defined for all the properties, but rather if ?s
has a value greater than two for any of the specified properties, you'll be able to find it. In some of your original queries, where you have patterns analogous to
?s :prop1 ?value1 ;
:prop2 ?value2 ;
:prop3 ?value3 .
you only get bindings for ?s
for resources that have a value for :prop1
and a value for :prop2
and a value for :prop3
.
In the case that the individuals don't all have values for all the properties, things become a bit trickier, because you need to optionally match the values, since some won't be present. This isn't much harder though. Just put the parts that might not be present inside of optional
blocks:
select ?s where {
?s a :desiredType .
optional { ?s :prop1 ?value1 }
optional { ?s :prop2 ?value2 }
optional { ?s :prop3 ?value3 }
filter ( ?value1 > 2 || ?value2 < 5 || ?value3 = 42 )
}