SPARQL Querying multiple ORs in the same filter
Asked Answered
G

1

9

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) 

  } 
Gaston answered 9/5, 2014 at 9:40 Comment(5)
You can use more than two conditions in a filter. We can't say what any of these should return unless you also share your data, though. The fact that you're using a different URI for the prefix ww: in the difference examples is a big red flag, though. Until it's edited, this question could be closed for the reason: "This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself."Continuate
@JoshuaTaylor I updated the topic. Is it more clear now?Gaston
Actually, you removed a lot from the question, and that changes the context, I think. In your original posting, you had filter ( ... || ... || ... ), which means "keep solutions that satisfy x or y or z". Now you've got filter ... filter ... filter ..., which means "keep solutions that satisfy x and y and z", which is very different. You need to show the data and the results you're trying to achieve, and you haven't done that yet.Continuate
But what the update does add, and I think this will be important, is that not every individual has values for each property. That means that you're going to need some optional matching. That's not too hard. I'll update my answer…Continuate
@JoshuaTaylor Didnt know that several filters means "and... and". Thus || is correct for my case. And yes not every individual has values for each property. Thats why while I query them as singles it returns results, but when I try them multiple at the same query it wont respond. I will update the post with data and desired resultsGaston
C
18

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.

When the individuals have values for all the properties

Using the values construct, we can provide some data in the query and see that a multi-way || works:

prefix : <https://mcmap.net/q/1143392/-sparql-querying-multiple-ors-in-the-same-filter/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 |
-------

If the conditions are the same

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.

When the individuals don't value values for all the properties

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 )
}
Continuate answered 9/5, 2014 at 11:0 Comment(7)
Problem is that for some of the properties I need them to be for example <2 and others >2 or =2. So I need different filters I guess. Indeed the selected variable doesnt have to include all these properties. As long as it satisfies one of them it should be "printed".Gaston
OK, so the real query can't be condensed so nicely. Even so, the first query, with explicit multiple conditions, works, right?Continuate
As you said not all individuals have all the properties asserted. So it does not really work for this case. Plus it is a bit complicated to combine the results (individuals of class:WWS that satisfy the conditions of different properties) in the same variable.Gaston
@Gaston Right, I understand that now, but your original example didn't show that the values had different conditions, so it looked like an easier problem. I'll update the answer soon to show how this is done with optional.Continuate
@Gaston OK, I've updated the answer. It includes examples with optional.Continuate
Oh yes thats right! It works properly. Is it possible to add to the FILTER among the ORs an AND condition for two variables. Something like this? (?value1 > 2 || ?value2 < 5 || (?value3 > 2 && value < 4) )Gaston
Yes, the conditions can be arbitrarily complex. There's probably some precedence order specified in the specification about the different boolean operators, but be sure to use proper parentheses anyway: it make things much easier to read.Continuate

© 2022 - 2024 — McMap. All rights reserved.