Sparql skos:broader
Asked Answered
M

4

5

I'm doing a SPARQL query on the DBpediaset, but I am having some issues (due to lack of detailed SPARQL knowledge) with a query limitation:

I first 'get' all music artists:

?person rdf:type <http://dbpedia.org/ontology/MusicalArtist> .

But I want to limit this to the broader category Category:American_musicians (via traversing skos:broader?): how?

*= while the question is specific, I've encountered this quest many times when wanting to running sparql queries.

Misnomer answered 21/7, 2010 at 14:16 Comment(1)
I think you would want an sparql engine with reasoning to do this, in theory the engine can know that broarder is transative and perfrom the query. However this is not something you can get as standard.Hamlin
H
5

This can be made easier with property paths in SPARQL 1.1

SELECT DISTINCT ( ?person )
WHERE
{
  ?person rdf:type dbpedia-owl:MusicalArtist .
  ?person skos:subject  skos:broader* category:American_musicians  .
}

Here it displays all the ancestors that could be reached via the skos:broader property.

Hedden answered 30/1, 2013 at 2:31 Comment(1)
Where do I find a SPARQL 1.1 DBpedia endpoint? I tried putting the query into snorql but it failed: dbpedia.org/snorql/…*+category%3AAmerican_musicians++.%0D%0A%7DCyme
S
2

I'm amazed this simple question hasn't been answered correctly in 3 years, and how much uncertainty and doubt people spread.

SELECT * { ?person a dbo:MusicalArtist . filter exists {?person dct:subject/skos:broader* dbc:American_musicians} }

  • corrected a few prefixes: dbo instead of the long dbpedia-owl, dbc instead of category. These short prefixes are builtin to DBpedia
  • corrected skos:subject (no such prop exists) to dct:subject
  • corrected the query with property paths, it was missing /
  • skos:broader is not transitive, skos:broaderTransitive is. However, DBpedia doesn't have the latter (no transitive reasoning)
  • replaced DISTINCT which is expensive with FILTER EXISTS which is much faster. The FILTER can stop at the first relevant sub-category it finds, while the original query first finds all such sub-cats per artist, then discards them (DISTINCT), sorts the artists in memory and removes duplicates.
Superstar answered 25/1, 2017 at 7:25 Comment(1)
FWIW some of the answers are 5 years old. I believe that at the time the DBPedia endpoint had very incomplete support for property paths.Forty
P
1

There's no really good way to do this, but here's a verbose way:

SELECT DISTINCT ( ?person )
WHERE
{
  ?person rdf:type dbpedia-owl:MusicalArtist .
  {
    ?person skos:subject [ skos:broader category:American_musicians ] .
  } UNION {
    ?person skos:subject [ skos:broader [ skos:broader category:American_musicians ] ] .
  } UNION {
    ?person skos:subject [ skos:broader [ skos:broader [ skos:broader category:American_musicians ] ] ] .
  } UNION {
    ?person skos:subject [ skos:broader [ skos:broader [ skos:broader [ skos:broader category:American_musicians ] ] ] ] .
  } UNION {
    ?person skos:subject [ skos:broader [ skos:broader [ skos:broader [ skos:broader [ skos:broader category:American_musicians ] ] ] ] ] .
  } UNION {
    ?person skos:subject [ skos:broader [ skos:broader [ skos:broader [ skos:broader [ skos:broader [ skos:broader category:American_musicians ] ] ] ] ] ] .
  } UNION {
    ?person skos:subject [ skos:broader [ skos:broader [ skos:broader [ skos:broader [ skos:broader [ skos:broader [ skos:broader category:American_musicians ] ] ] ] ] ] ] .
  }
}

For figuring out how many levels you need, you can change SELECT DISTINCT to SELECT COUNT DISTINCT and stop adding levels when the count stops going up.

Procurance answered 21/7, 2010 at 15:49 Comment(0)
W
0

This is really easy to perform in neo4j. An alternative to accomplish your task in SPARQL could be to extract all the subgraph under "Category:American_musicians" by iterating via code on subcategories.

Eg. pseudo code in java would be something like:

String startCategory = "<http://dbpedia.org/resource/Category:American_musicians>";
iterateTraversalFunction(startCategory);

then the traversal function would be:

public void iterateTraversalFunction(String startCategory){
     ArrayList<String> artistsURI = // SPARQL query ?person skos:subject startCategory . ?person rdf:type MusicalArtist 

    ArrayList<String> subCategoriesURI = // SPARQL query ?subCat skos startCategory
    // Repeat recursively
   for(String subCatURI: subCategoriesURI){
       iterateTraversalFunction(subCatURI);
   }
}

Hope this helps, - Dan

Winslow answered 2/12, 2012 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.