2
votes

I'm developing my own Fuseki endpoint from some DBpedia data. I'm in doubt on how to aggregate properties related to a single resource.

SELECT ?name ?website ?abstract ?genre ?image
WHERE{
VALUES ?s {<http://dbpedia.org/resource/Attack_Attack!>}
  ?s  foaf:name ?name ;
      dbo:abstract ?abstract .
  OPTIONAL { ?s dbo:genre ?genre } .
  OPTIONAL { ?s dbp:website ?website } .
  OPTIONAL { ?s dbo:image ?image } .
  FILTER LANGMATCHES(LANG(?abstract ), "en")
}

SPARQL endpoint: http://dbpedia.org/sparql/

This query returns 2 matching results. They are different just for the dbo:genre value. There is a way I can query the knowledge base and retrieving a single result with a list of genres?

2
The first triple pattern is unnecessary as it denotes a property RDF triple with no variables. Moreover, VALUES can be used to make the query more compact, see my edited query. - UninformedUser

2 Answers

3
votes

@chrisis's query works well on the DBpedia SPARQL Endpoint, which is based on Virtuoso.

However, if you are using Jena Fuseki, you should use more conformant syntax:

PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>

SELECT
?name
(SAMPLE(?website) AS ?sample_website)
(SAMPLE(?abstract) AS ?sample_abstract)
(SAMPLE(?image) AS ?sample_image)
(GROUP_CONCAT(?genre; separator=', ') AS ?genres)
WHERE {
  VALUES (?s) {(<http://dbpedia.org/resource/Attack_Attack!>)}
  ?s  foaf:name ?name ;
      dbo:abstract ?abstract .
  OPTIONAL { ?s dbo:genre ?genre } .
  OPTIONAL { ?s dbp:website ?website } .
  OPTIONAL { ?s dbo:image ?image} .
  FILTER LANGMATCHES(LANG(?abstract ), "en")
} GROUP BY ?name

The differences from the @chrisis's query are:

  • Since GROUP_CONCAT is an aggregation function, it might be used with GROUP BY only;
  • Since GROUP BY is used, all non-grouping variables should be aggregated (e.g. via SAMPLE);
  • GROUP_CONCAT syntax is slightly different.

In Fuseki, these AS in the projection are in fact superfluous: see this question and comments.

2
votes

Yes, the GROUP_CONCAT() function is what you want.

SELECT ?name ?website ?abstract (GROUP_CONCAT(?genre,',') AS ?genres) ?image
WHERE{
  <http://dbpedia.org/resource/Attack_Attack!> a dbo:Band ;
       foaf:name ?name;
      dbo:abstract ?abstract .
  OPTIONAL{   <http://dbpedia.org/resource/Attack_Attack!> dbo:genre ?genre } .
  OPTIONAL{   <http://dbpedia.org/resource/Attack_Attack!> dbp:website ?website} .
  OPTIONAL{   <http://dbpedia.org/resource/Attack_Attack!> dbo:image ?image} .
FILTER LANGMATCHES(LANG(?abstract ), "en")

}