DIt klopt niet meer, moet herschreven worden
Contents
Tweets in MongoDB
zie ook: /WeekCompact
Invoer
Ik maak twee collecties aan in de database twitter:
tweets |
de individuele tweets, zonder profiel-info van users |
users |
profiel-info van users, 1 per user, alleen de laatste versie die is verwerkt |
Ik gebruik inserttweets.go om tweets in te voeren in MongoDB.
De invoer is ge-gzipt-te data, tweets in json-formaat, één tweet per regel.
Ik probeer alleen Nederlandstalige tweets op te nemen. Eerst laat ik alle tweets weg van gebruikers die hun taalvoorkeur op iets anders dan Nederlands of Engels hebben ingesteld. (Engels is de default als mensen geen taal hebben ingesteld.) Van de rest van de tweets haal ik alle @-mentions, hashtags, url's en het woordje RT weg. Wat ik overhou van een tweet laat ik door libtextcat analyseren, waarbij ik alleen patronen voor Nederlands en Engels gebruik. Als libtextcat Nederlands als een van de mogelijkheden geeft, of als het libtextcat niet lukt de taal te bepalen, dat laat ik de tweet er in. Anders, dus als libtextcat Engels als enig antwoord geeft, gooi ik de tweet weg.
Het resultaat van libtextcat voeg ik toe aan de tweet als item TEXTCAT. Dit is een lijst, omdat er meer dan één mogelijkheid kan zijn. Wil je strict selecteren op Nederlands, gebruik dan deze query:
{db.tweets.find( $and: [ {TEXTCAT:"nl"}, {TEXTCAT:{$ne:"en"}} ] } )
Of deze query:
db.tweets.find( {TEXTCAT:{$nin:["en","UNKNOWN","SHORT"]}} )
De tweet compleet met @-mentions, hashtags, etc. haal ik door de tokenizer uit /net/aistaff/vannoord/z/Alpino/Tokenization/libtok.c. Daarna wordt ie op spaties opgesplitst, en alle woorden worden opgeslagen als een array als item WORDS. Elk woord in de array ziet er zo uit:
{
"word" : "Ik", // woord
"lcword" : "ik", // woord omgezet naar lowercase
"cat" : "" // category
}
Mogelijke waardes voor category:
@ |
@-mention |
# |
hashtag |
u |
url |
r |
het woordje RT (alleen uppercase) |
. |
overigen zonder letters (a-z, A-Z), dus interpunctie, cijfers, smileys, Chinese tekst... |
(leeg) |
de rest |
Tweets worden opgeslagen zonder deze elementen:
user: inhoud hiervan wordt apart opgeslagen in collectie users, maximaal 1 per id
- retweeted_status
De volgende elementen worden aan tweets toegevoegd:
USER_id_str |
het subelement user.id_str |
RETWEETED_STATUS_id_str |
het subelement retweeted_status.id_str, indien aanwezig |
RETWEETED_STATUS_USER_id_str |
het subelement retweeted_status.user.id_str, indien aanwezig |
CREATED_AT_DATE |
string in formaat "2012-01-01", "2012-12-31" |
CREATED_AT_TIME |
string in formaat "00:00:00" tot "23:59:59" |
CREATED_AT_YEAR |
|
CREATED_AT_MONTH |
|
CREATED_AT_DAY |
dag van de maand |
CREATED_AT_WEEKDAY |
van 0 = zondag tot 6 = zaterdag |
CREATED_AT_HOUR |
0 tot 23 |
CREATED_AT_MINUTE |
|
CREATED_AT_SECOND |
|
CREATED_AT_ZONE |
"CET", "CEST" |
TEXTCAT |
["nl"], ["nl","en"], ["en","nl"], ["SHORT"], ["UNKNOWN"] zie boven |
WORDS |
zie boven |
Alle data/tijden zijn voor tijdzone Europe/Amsterdam.
Tweets sorteren op chronologische volgorde kan zo:
db.tweets.find().sort({CREATED_AT_DATE:1, CREATED_AT_TIME:1})
Schijfruimte
Opslag van alle tweets van 1 april 2012 (3.037.478 tweets, 566.103 users) gebruikt 10Gb.
Opslag van alle tweets van de eerste zeven dagen van april 2012 (18.192.427 tweets, 1.505.358 users) gebruikt 34Gb.
Snelheid
Invoer van alle tweets van 1 april 2012, vanaf volker:
Database onder /data: 1 uur, 11 minuten
Database onder /net: 1 uur, 45 minuten (maar met meer indexen)
In het begin gebruikt het invoerprogramma zo'n 60% van de CPU, de mongo deamon onder de 20%. Bij de invoer van data voor dag 7 (alleen database onder /net) zijn beide getallen gezakt tot onder de 10%. De bottleneck lijkt te zitten in disk/IO, en die is bijzonder traag voor data die onder /net staat:
Een test met deze query, nadat de data van 1 dag was ingevoerd:
print(db.tweets.find({text:/fiets/i}).count())
De eerste keer duurt dit met de database onder /net 1 minuut 8, met de database onder /data slechts 8 seconde.
Bij de tweede keer, direct er na, is het bij database onder /net 7,7 seconde, onder /data 7,6 seconde. In dit geval is de data ergens gecachet in de mongo deamon, maar dat is niet meer mogelijk als er veel meer data is opgeslagen.
Statistiek
Data van heel april 2012
datafiles |
335 gigabytes |
|
tweets |
84.668.210 |
|
gebruikers |
3.312.539 |
|
woorden |
767.845.646 |
exclusief de dingen die volgen |
interpunctie |
180.421.291 |
|
@-mentions |
61.202.031 |
|
het woordje RT |
20.885.561 |
|
hashtags |
15.421.635 |
|
url's |
6.741.452 |
Voorbeeld
bestand groningen.js:
// vind tweets in de buurt van Groningen
db.tweets.ensureIndex({"coordinates.coordinates":"2d"})
groningen = [6.5670, 53.21853] // stadhuis: long, lat
straal = 6.283185 / 40030.0 * 8.0 // 8 kilometers omgerekend naar radialen
var cursor = db.tweets.find(
{"coordinates.coordinates":{$within:{$centerSphere:[groningen, straal]}}},
{text:true, USER_id_str:true}
)
while (cursor.hasNext()) {
tweet = cursor.next()
user = db.users.findOne(
{id_str:tweet["USER_id_str"]},
{screen_name:true, location:true}
)
print((user["screen_name"] + " (" + user["location"] + "): " + tweet["text"]).replace(/\s+/g, " "))
}
database op netwerk (poort 27017), vanaf volker, shell:
mongo --quiet 127.0.0.1:27017/twitter groningen.js | less
lokale database (poort 27018), vanaf volker, shell:
mongo --quiet 127.0.0.1:27018/twitter groningen.js | less
Documentatie
Systemen
Bronnen
Attachments
Download alles: TwitterData.tar.gz