Search code examples
sparqlrdf

Sparql query to get only top-most elements matching criteria


I have multiple trees where nodes are linked with hasParent and each node has some particular color. I need to filter a tree by a color and extract the topmost elements (exclude nested elements after filtering).

Here is an example of my data:

enter image description here

The result I need is: [A, B, I].

I know how to implement basic tree filter that returns [A, B, I, J, L, O]:

SELECT DISTINCT ?s WHERE {
  ?s <http://looneytunes-graph.com/color> "yellow"^^xsd:string
}

Is there a way to implement such additional filtering? or do I need to rethink my solution and use something else instead of graph db (AWS Neptune)?

I'm testing it with https://sparql-playground.sib.swiss/data and the following data:

@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<http://looneytunes-graph.com/A> <http://looneytunes-graph.com/color> "yellow"^^xsd:string .

<http://looneytunes-graph.com/B> <http://looneytunes-graph.com/color> "yellow"^^xsd:string .

<http://looneytunes-graph.com/C> <http://looneytunes-graph.com/color> "green"^^xsd:string .

<http://looneytunes-graph.com/D> <http://looneytunes-graph.com/color> "red"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/A> .

<http://looneytunes-graph.com/E> <http://looneytunes-graph.com/color> "blue"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/A> .

<http://looneytunes-graph.com/F> <http://looneytunes-graph.com/color> "blue"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/B> .

<http://looneytunes-graph.com/G> <http://looneytunes-graph.com/color> "green"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/B> .

<http://looneytunes-graph.com/H> <http://looneytunes-graph.com/color> "red"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/C> .

<http://looneytunes-graph.com/I> <http://looneytunes-graph.com/color> "yellow"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/C> .

<http://looneytunes-graph.com/J> <http://looneytunes-graph.com/color> "yellow"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/D> .

<http://looneytunes-graph.com/K> <http://looneytunes-graph.com/color> "green"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/D> .

<http://looneytunes-graph.com/L> <http://looneytunes-graph.com/color> "yellow"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/F> .

<http://looneytunes-graph.com/M> <http://looneytunes-graph.com/color> "red"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/G> .

<http://looneytunes-graph.com/N> <http://looneytunes-graph.com/color> "blue"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/G> .

<http://looneytunes-graph.com/O> <http://looneytunes-graph.com/color> "yellow"^^xsd:string ;
    <http://looneytunes-graph.com/hasParent> <http://looneytunes-graph.com/I> .

Solution

  • SELECT DISTINCT ?s WHERE {
      ?s <http://looneytunes-graph.com/color> "yellow"^^xsd:string .
      FILTER NOT EXISTS {
         ?s hasParent+ [<http://looneytunes-graph.com/color> "yellow"^^xsd:string] .
      }
    }
    

    With this query you are filtering out the nodes having (a parent node having a parent node having...) a yellow parent node.