Search code examples
sparqlrdffuseki

Matching attribute sets using SPARQL


This question is about finding matching candidate and path using a triple store with SPARQL endpoint (Fuseki 3.8.0).

The matching criteria is that the attribute's of a candidate must contain all of the requires of a path. In the minimal example data below, the matches should be candi_1 with path_1 and candi_2 with path_2.

@prefix : <http://example.com/app#> .

:candi_1
  a :candidate ;
  :attribute "A", "B", "C" .

:candi_2
  a :candidate ;
  :attribute "C", "D" .

:candi_3
  a :candidate ;
  :attribute "C", "E" .

:path_1
  a :path ;
  :requires "A", "C" .

:path_2
  a :path ;
  :requires "C", "D" .

The result should be:

+------------+-------------+
| ?candidate | ?valid_path |
+------------+-------------+
| :candi1    | :path1      |
| :candi2    | :path2      |
+------------+-------------+

Solution

  • A kind of double negation:

    PREFIX : <http://example.com/app#> 
    
    SELECT ?cand ?path
    WHERE {
      ?cand a :candidate . 
      ?path a :path . 
      FILTER NOT EXISTS {
        ?path :requires ?attr .
        FILTER NOT EXISTS {
          ?cand :attribute ?attr .
        }
      }
    }
    

    The above query shouldn't be very performant. Try also the following one:

    PREFIX : <http://example.com/app#> 
    
    SELECT ?cand ?path
    {
        {
        SELECT (COUNT(?attr) AS ?count) ?path ?cand
            {
            ?path a :path ; :requires ?attr .
            ?cand a :candidate ; :attribute ?attr . 
            } GROUP BY ?path ?cand
        } 
        {
        SELECT (COUNT(?attr) AS ?count) ?path
            {
            ?path a :path ; :requires ?attr .
            } GROUP BY ?path
        }
    }
    

    However, the latter query shouldn't work if "empty" candidates and paths exist.