Agregando resultados de la consulta SPARQL

Estoy consultando un conjunto de datos de tweets:

SELECT * WHERE { ?tweet smo:tweeted_at ?date ; smo:has_hashtag ?hashtag ; smo:tweeted_by ?account ; smo:english_tweet true . FILTER ( ?date >= "20130722"^^xsd:date && ?date < "20130723"^^xsd:date ) } 

Si un tweet tiene múltiples hashtags, hay una fila en el conjunto de resultados por hashtag. ¿Hay alguna manera para que agregue los hashtags en una matriz en su lugar?

Puedes GROUP_CONCAT por las variables que identifican el tweet y luego usar GROUP_CONCAT para concatenar los hashtags en algo así como una matriz, pero seguirá siendo una cadena que necesitarás analizar posteriormente. Por ejemplo, datos dados como

 @prefix smo:  . @prefix :  . :tweet1 smo:tweeted_at "1" ; smo:has_hashtag "tag1", "tag2", "tag3" ; smo:tweeted_by "user1" ; smo:english_tweet true . :tweet2 smo:tweeted_at "2" ; smo:has_hashtag "tag2", "tag3", "tag4" ; smo:tweeted_by "user2" ; smo:english_tweet true . 

puedes usar una consulta como

 prefix smo:  select ?tweet ?date ?account (group_concat(?hashtag) as ?hashtags) where { ?tweet smo:tweeted_at ?date ; smo:has_hashtag ?hashtag ; smo:tweeted_by ?account ; smo:english_tweet true . } group by ?tweet ?date ?account 

para obtener resultados como:

 -------------------------------------------------- | tweet | date | account | hashtags | ================================================== | smo:tweet2 | "2" | "user2" | "tag4 tag3 tag2" | | smo:tweet1 | "1" | "user1" | "tag3 tag2 tag1" | -------------------------------------------------- 

Puede especificar el delimitador utilizado en la concatenación de grupo, de modo que si hay algún carácter que no puede aparecer en hashtags, puede usarlo como delimitador. Por ejemplo, suponiendo que | no puede aparecer en hashtags, puede usar:

 (group_concat(?hashtag;separator="|") as ?hashtags) 

en cambio y consigue

 -------------------------------------------------- | tweet | date | account | hashtags | ================================================== | smo:tweet2 | "2" | "user2" | "tag4|tag3|tag2" | | smo:tweet1 | "1" | "user1" | "tag3|tag2|tag1" | -------------------------------------------------- 

Si está trabajando en un lenguaje que tiene cierta syntax de matriz literal, incluso podría replicar eso:

 (concat('[',group_concat(?hashtag;separator=","),']') as ?hashtags) 
 ---------------------------------------------------- | tweet | date | account | hashtags | ==================================================== | smo:tweet2 | "2" | "user2" | "[tag4,tag3,tag2]" | | smo:tweet1 | "1" | "user1" | "[tag3,tag2,tag1]" | ---------------------------------------------------- 

Ahora, no afecta los datos aquí, pero group_concat realmente incluirá duplicados en la concatenación si están presentes en los datos. Por ejemplo, de lo siguiente (donde solo estoy proporcionando datos con values por el ejemplo):

 prefix :  select ?tweet (concat('[',group_concat(?hashtag;separator=','),']') as ?hashtags) where { values (?tweet ?hashtag) { (:tweet1 "tag1") (:tweet1 "tag1") (:tweet1 "tag2") (:tweet1 "tag3") (:tweet2 "tag2") (:tweet2 "tag3") (:tweet2 "tag4") } } group by ?tweet 

obtenemos resultados que incluyen [tag1,tag1,tag2,tag3] , es decir, se incluye el valor duplicado de ?hashtag :

 ------------------------------------- | tweet | hashtags | ===================================== | :tweet2 | "[tag2,tag3,tag4]" | | :tweet1 | "[tag1,tag1,tag2,tag3]" | ------------------------------------- 

Podemos evitar esto usando group_concat(distinct ?hashtag;...) :

 prefix :  select ?tweet (concat('[',group_concat(distinct ?hashtag;separator=','),']') as ?hashtags) where { values (?tweet ?hashtag) { (:tweet1 "tag1") (:tweet1 "tag1") (:tweet1 "tag2") (:tweet1 "tag3") (:tweet2 "tag2") (:tweet2 "tag3") (:tweet2 "tag4") } } group by ?tweet 
 -------------------------------- | tweet | hashtags | ================================ | :tweet2 | "[tag2,tag3,tag4]" | | :tweet1 | "[tag1,tag2,tag3]" | --------------------------------