2013-08-13 14 views
10

sto interrogazione di un set di dati di tweets:risultati aggregazione dai interrogazione SPARQL

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) 
} 

Se un tweet ha più hashtag, c'è una riga nel set di risultati per hashtag. C'è un modo per me di aggregare gli hashtag in un array, invece?

risposta

26

È possibile effettuare il GROUP BY dalle variabili che identificano il tweet e quindi utilizzare GROUP_CONCAT per concatenare gli hashtag in qualcosa di simile a un array, ma sarà comunque una stringa che sarà necessario analizzare successivamente. Per esempio, data di dati come

@prefix smo: <http://example.org/> . 
@prefix : <http://example.org/> . 

: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 . 

è possibile utilizzare una query come

prefix smo: <http://example.org/> 

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 

per ottenere risultati come:

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

È possibile specificare il delimitatore utilizzato nella concatenazione di gruppo, in modo da se c'è qualche carattere che non può apparire negli hashtag, puoi usarlo come delimitatore. Per esempio, supponendo che | non può apparire in hashtags, è possibile utilizzare:

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

invece e ottenere

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

Se si lavora in una lingua che ha una sintassi array letterale, è potrebbe anche essere in grado di replicare che:

(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]" | 
---------------------------------------------------- 

Ora, non influisce sui dati qui, ma group_concat includerà effettivamente i duplicati nella concatenazione se sono presenti nei dati. Ad esempio, una delle seguenti opzioni (dove sto solo fornendo dati con values per il bene di questo esempio):

prefix : <http://example.org/> 

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 

otteniamo risultati tra cui [tag1,tag1,tag2,tag3], vale a dire, il valore duplicato di ?hashtag è incluso:

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

possiamo evitare questo utilizzando group_concat(distinct ?hashtag;...):

prefix : <http://example.org/> 

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]" | 
-------------------------------- 
+0

Grazie! Era esattamente ciò di cui avevo bisogno. Non ho incontrato group_concat in nessuna delle esercitazioni che ho trovato. – betseyb

+0

@BetseyBenagh Sì, sono sorpreso che alcune delle funzioni impostate in SPARQL 1.1 non compaiano un po 'più in risalto nel sommario delle specifiche. –

+1

In alternativa alla soluzione con 'GROUP_CONCAT' fornita qui, puoi anche usare l'aggregato' SAMPLE' - che invece di concatenare tutti i valori prende solo un singolo valore. –

Problemi correlati