Skip to content

Instantly share code, notes, and snippets.

@mhermans
Created April 18, 2011 19:45
Show Gist options
  • Save mhermans/926022 to your computer and use it in GitHub Desktop.
Save mhermans/926022 to your computer and use it in GitHub Desktop.
NOSQL

NOSQL: subjectieve intro (van iemand zonder DB-ervaring):

Onder de noemer/hype van NOSQL/alternatief voor SQL vallen een aantal gerelateerde benaderingen, twee interessante:

  • key-value stores, met als leukste voorbeeld redis
  • graph-databases, met als koploper neo4j

Key-value stores zijn zeer minimalistische databases, bedoelt voor zeer low-level bewerkingen, zonder schema, indexen etc. Als je heel goed weet wat je (algoritmes) aan het doen zijn kun je er blijkbaar serieus performante, gedistribueerde zaken mee doen. Dit gaat m'n petje/praktische noden te boven, wél interessant is om persistence hebben als je python code aan het schrijven bent.

Om je data te bewaren tussen bv. cleaning-sessies, of door te geven naar andere scripts kun je bv. de modules shelve of pickle gebruiken, of de moeite doen om bv. een sqlite databaseje te gebruiken. De eerste oplossing had ik altijd schrik om iets te corrumperen (bv. door concurrent accesss door twee scripts, te grote bestanden,etc.), de tweede was vaak teveel moeite (sql schrijven, schema's, tables, etc.).

Key-value stores en vooral redis zitten perfect tussen de twee oplossingen in: het gemak van persisent standaard datastructuren te hebben (list, hash, set, etc.) en de voordelen van een server, zonder de overhead van sql, schema's etc. Zie deze presentatie.

bv. je hebt een script data xml/csv inleest (pseudocode, kan niet debuggen op trein)::

import csv, redis # https://github.com/andymccurdy/redis-py
r = redisClient('localhost')
for record in csv.CSVreader.rows(): # 3 cols
    id = record[0] # eerste row is een soort identifier
    r.hmset(id, dict(zip(['id', 'name', 'address'], record) # stop de values in een hash met als key de 'id'-waarde

Ergens anders (zelfde script, andere terminal of computer, maakt niet uit):

r = redisClient('192....')
id = x # will bedrijf hebben met bepaalde id
c = r.hget(x, 'adress') # get value voor key 'adress' voor key x
lat, long = geoCode(c)
r.hset(x, 'latitude', lat)
r.hset(x, 'longitude', long)
r.lpush('geocoded', x) # add id of geocoded company to list 'geocoded'

In nog een ander script, bv. visualisatie:

r = redisClient('192....')
for id in r.get('geocoded'):
    addToMap(r.hget(id, 'latitude'), r.hget(id, 'longitude'))

Queries gaan razend snel, het ene script kan nog aant lopen zijn terwijl je in een andere terminal ook aan het lezen/schrijven bent, alles zit mooi in de db als je je pc afzet, etc.

Heb het zelf nog maar een dikke week in gebruik (sinds dat ik mijn zwitserse data moet cleanen, 800k records), maar zeker eens naar kijken. Ook bijzonder makkelijk om op te zetten:

download
tar -xzf redis.tar.gz
cd redis/src
make
redis-server # server draait, geen schema, kan beginnen
redis-cli # command line om te oefenen, ook [online](http://try.redis-db.com/): 

Dit fimpje absoluut eens bekijken. Een foreach functie is aan het lopen in Rstudio, om een bootstrap uit te voeren, 1 commando op een andere pc/server en hij heeft de lopende bootstrap geparelliseerd (de resultaten/communicatie loopt via een redis server).

Het tweede NOSQL voorbeeld dat ik de moeite waard vind is een graphdatabase, met neo4j als beste voorbeeld. Ik heb ad telefoon al kort uitgelegt waar ik ze nuttig vind. Dit is echter een complexer dan een key-value store, en ook een andere manier van denken dan een sql-database. Ik ben nog niet verder dan "proof of concept"-stadium.

Neo4j heeft imho het meest gevestigde project (open source), met een dynamische community. Je kan werken via java (of de language bindings voor java, e.g. jruby, jython) of via de REST interface. Zie intro-presentatie.

Dit laatste is een aardig pluspunt: het REST protocol maakt gebruik van standaard HTTP technieken (& JSON) en is dus heel transparant om te debuggen, etc. Alle bewerkingen en gegevens in de database zijn ook beschikbaaar via de REST interface wat het relatief makkelijk maakt om er iets voor te ontwikkelen: je moet niet de codebase van het onderliggend project kennen, of in java zaken schrijven, je kan in de programmeertaal/omgeving naar keuze werken (alles heeft wel een http en een json library).

Stel dat je bv. een cool prototype in neo4j ontwikkeld, maar je wil het showen via een SAS interface/dashboard ding. Je moet dan niet SAS en neo4j via java integreren, maar via SAS http requests maken & de json responses verwerken, wat een stuk beter doenbaar is (niet de top perfomantie, maar wel goed voor prototypes).

De REST-interface heeft behoorlijke Python bindings, zodat je bv. volgende bewerkingen kan doen:

from neo4jrestclient import GraphDatabase
gdb = GraphDatabase("http://localhost:7474/db/data/")
p = gdb.node(income=1000)
c = gdb.node(name='SAS')
c.Employee(p, since='2010')
c.traverse(types=[neo4jrestclient.Undirected.Employee])
=> node p

Nog interessanter wordt het als je je datamodel kan integreren met het graph model, door de nodes te subclassen, bv. Person(Node), zodat je object-logica en de graphdatabase logica samenvallen. Spijtig genoeg zijn de python bindings niet 100% up to date met de laatste versie. Ze hebben belooft om er tijd in te steken, maar ik weet momenteel niet of ik daar moet op wachten, of naar de Ruby-bindings overschakel, die wel héél goed zijn uitgewerkt & gedocumenteerd.

Ga via de homepage van neo4j eens naar hun blog of twitter stream, daar kom je interessante applicaties tegen die neo4j gebruiken.

M

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment