SPARQL filter regex and union

2019-09-10 10:39发布

问题:

My ontology has 2 classes: food foodSource. I want to get the data for the class food with 2 kinds of foodSource using the SPARQL query:

SELECT ?food ?foodSource ?foodSource2
WHERE {
  {
    ?foodSource mpasi:data_memerlukanBahan ?memerlukanBahan.
    ?food ?memerlukanBahan ?value.
    FILTER  regex(str(?foodSource),"carrot")
  }
  UNION
  {
    ?foodSource2 mpasi:data_memerlukanBahan ?memerlukanBahan.
    ?food ?memerlukanBahan ?value.
    FILTER  regex(str(?foodSource2),"tomato")
  }
} 
order by ?food

I get the correct result. But then I want to avoid some food sources. So, how do can I get food that doesn't have a food source? For example, I have 3 kinds of food:

  • kedelai porridge
  • apple crumble
  • tomato soup

Then i want food without apple inside it. So, naturally i just get kedelai porridge and tomato soup. Can i get it using !regex?

FILTER  (!regex(str(?foodSource),"apple")).

回答1:

Perhaps a first step is to refactor your UNION statement. The first two triple patterns are the same for both UNION graph statements, so move those outside of your UNION statement. Then you're left with just the two FILTER statements, which can be re-written with an || expression:

SELECT ?food ?foodSource ?foodSource2
WHERE {
  ?foodSource mpasi:data_memerlukanBahan ?memerlukanBahan.
  ?food ?memerlukanBahan ?value.
  FILTER (regex(str(?foodSource),"carrot") || regex(str(?foodSource2),"apple"))
}

Perhaps better, as @AKSW suggests, is to perform the or in the regex itself:

FILTER regex(str(?foodSource),"carrot|apple")

Since FILTER in SPARQL is a positive filter - it states what to let through - then "carrot" and "apple" are the only possible solutions. "potato" can't get through the filter.

However if you wanted to find everything but "potato", then you have a couple of negation choices:

FILTER (!regex(str(?foodSource),"potato"))

or via regex negation:

FILTER regex(str(?foodSource),"[^potato]")