Reputation: 60213
How to get that in SPARQL?
In particular, if both cat and animal have icons, then I want to get cat's icon rather than animal's icon, because it is closer to Grumpy Cat.
If the item is an instance of several classes, or if a class is a sub-class of several classes, it would be great if all branches could be explored, and the closest icon chosen. Performance is quite important, I hope the query can run in less than a second on https://query.wikidata.org . I have tried writing a query based on imbricated MINUS clauses, but it is not really recursive.
If needed for test purposes, here are many Wikidata items with icons.
Upvotes: 1
Views: 367
Reputation: 2277
You can't recursively look for something in SPARQL, and then stop when you find the first one. What you can do is either get all the icons, a random icon, or define a finite amount of classes that you go through.
You can use a chain of optionals to get the closest icon (in the case where you define a static depth):
# SAMPLE is used here because 1) the resource might have multiple classes,
# and 2) because of the fallback below
SELECT ?item ?itemLabel ?cls ?clsLabel (SAMPLE(?icon) AS ?icon) WHERE {
BIND(wd:Q103474 AS ?item)
?item wdt:P31 ?cls.
OPTIONAL { ?cls wdt:P2910 ?icon. }
OPTIONAL { ?cls (wdt:P279/wdt:P2910) ?icon. }
OPTIONAL { ?cls (wdt:P279/wdt:P279/wdt:P2910) ?icon. }
OPTIONAL { ?cls (wdt:P279/wdt:P279/wdt:P279/wdt:P2910) ?icon. }
# You can continue the optionals with longer property paths,
# here we just fall back to trying the whole class path
# (returning all icons in the path in an arbitrary order).
OPTIONAL { ?cls (wdt:P279+/wdt:P2910) ?icon. }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?item ?itemLabel ?cls ?clsLabel
The first successful optional will bind ?icon
, and so this variable will hold the "closest" icon. The SAMPLE
will make sure the query only returns one icon.
Upvotes: 2