4

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.

Sirko
  • 72,589
  • 19
  • 149
  • 183
ymschaap
  • 61
  • 1
  • 5
  • 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. – Jeremy French Jul 26 '10 at 14:13

4 Answers4

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.

Ben Companjen
  • 1,417
  • 10
  • 24
user373480
  • 163
  • 2
  • 9
  • Where do I find a SPARQL 1.1 DBpedia endpoint? I tried putting the query into snorql but it failed: http://dbpedia.org/snorql/?query=SELECT+DISTINCT+%28+%3Fperson+%29%0D%0AWHERE%0D%0A%7B%0D%0A++%3Fperson+rdf%3Atype+dbpedia-owl%3AMusicalArtist+.%0D%0A++%3Fperson+skos%3Asubject++skos%3Abroader*+category%3AAmerican_musicians++.%0D%0A%7D – dranxo Feb 19 '14 at 20:40
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.
Vladimir Alexiev
  • 2,477
  • 1
  • 20
  • 31
  • 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. – Jeen Broekstra Jan 25 '17 at 07:36
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.

glenn mcdonald
  • 15,290
  • 3
  • 35
  • 40
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

Daniele
  • 359
  • 7
  • 15