Search code examples
sparqlrdf

How to write a sparql query with variable predicate?


Please have a look at the following example:

@prefix : <#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

:Bob :score 78 .
:John :score 50 .

:rule1 :condition [
        rdf:subject :score ;
        rdf:predicate :notLessThan ;
        rdf:object 60
     ];
     :condition [
        rdf:subject :score ;
        rdf:predicate :notGreaterThan ;
        rdf:object 80 
     ];
     :rating :passed .

:rule2 :condition [
        rdf:subject :score ;
        rdf:predicate :lessThan ;
        rdf:object 60
     ];    
     :rating :failed .

I want to get the following output by spqrql query:

 :Bob :rating :passed.    
 :John :rating :failed.

here rdf:predicate is changeable by the user, and its value may be:

 lessThan, notLessThan, greaterThan, notGreaterThan

So how do I write this SPARQL statement based on dynamic predicate?
I don't have any ideas. Thank you for helping me.


Solution

  • This does work perfectly :

    PREFIX : <#>
    PREFIX rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    PREFIX rdfs:    <http://www.w3.org/2000/01/rdf-schema#>
    
    CONSTRUCT {
        ?student :rating ?rating .
    } WHERE {
        ?student :score ?score .
        ?rule :rating ?rating .
        OPTIONAL {
           ?rule :condition ?condition .
           ?condition rdf:subject :score .
           ?condition rdf:predicate ?predicate .
           ?condition rdf:object ?object .
           # fails condition
           FILTER (
               ! ( (?predicate = :lessThan && ?score < ?object ) ||
                   (?predicate = :notLessThan && ?score >= ?object ) ||
                   (?predicate = :greaterThan && ?score > ?object ) ||
                   (?predicate = :notGreaterThan && ?score <= ?object )
               )
           )
        }
        FILTER(!bound(?condition))
    }
    

    and we get the results:

    :Bob    :rating  :passed .
    :John   :rating  :failed .