Nettverk
Vi i Shortcut har en hang mot alternativer til relasjonsdatabaser.
Det er mange gode grunner til å være glad i relasjonsdatabaser, men disse er ikke blant dem:
- Iterativ utvikling. Relasjonsdatabasene er veldig gode på å håndheve struktur på dataene sine. Dette betyr at man må fortelle databasen nøyaktig hvilke felter en tabell skal innehold og hva slags data som kan lagres i disse feltene. Innenfor iterativ/smidig utvikling har man gjerne en tendens til å ønske å dyrke datamodellen min mer som en kjøkkehage enn en romferge. Den rigide strukturen i relasjonsdatabasen kan derfor bli et irritasjonsmoment i et smidig prosjekt.
- Kompatibilitet med objektorientert utvikling. Relasjonsdatabasens hovedkonsepter er databaser, tabeller og rader. I tillegg har de fleste databasemotorer støtte for innebygd logikk (views, triggere, lagrete prosedyrer), og språket man snakker med mot relasjonsdatabasen heter SQL. Innenfor objektorientert utvikling har man objekter, klasser og metoder. Når man de seinere årene har fått ganske gode verktøy for å representere objekter i en relasjonsdatabase har dette mindre å gjøre med relasjonsdatabasens fortreffelighet enn dens utbredelse.
- Støtte for delvis strukturerte data. Som nevnt ovenfor er en av relasjonsdatabasens styrker at den har et strengt regime for hva slags type data den aksepterer. Skal en rad i en people-tabell kunne ha en first_name-kolonne må den kolonnen ligge i databaseskjemaet, punktum. Om man tar en kikk på en gjennomsnittlig databasedump fra et noen år gammelt system vil man oppdage at hver tabell plutselig har fått mange flere kolonner enn man opprinnelig tenkte. Dette er fordi skiftende behov har ført til at man må holde følge. Kanskje var det en kundegruppe som måtte ha et ekstra felt i databasen, så dukket det plutselig opp i databaseskjemaet uten at noen av de andre kundene trenger det. Dermed vil man se at det blir vanskeligere å vanskeligere å lese noen slags logikk ut fra databaseskjemaet, særlig når bare en av hundre rader har en verdi i en gitt kolonne.
- Støtte for nettverksorienterte data. Om du har jobbet med en relasjonsdatbase noen gang: tenk deg følgende scenario. Du har laget et sosialt nettsted (gjesp), der brukerne angir andre brukere som sine venner. Tenk så at kunden din kommer og vil vite hvordan en bruker X er koblet sammen med en bruker Y. Sett deg gjerne ned med penn og papir; jeg er villig til å vedde på at du kommer opp med en SQL-setning som får deg til å føle deg skikkelig macho.
Tenk deg så at databasen du brukte var orientert rundt relasjoner mellom objektene i systemet. At de to typen objekter som finnes i systemet var objekter og relasjoner mellom objekter. Tenk deg videre at denne databasen var skikkelig god på å følge disse relasjonene mellom objektene og ga deg et språk for å uttrykke hvordan X og Y er forbundet.
Våre venner i Java-verden har laget en slik database, som er orientert rundt en nettverksfilosofi. Og etter å ha dummet meg skikkelig ut har jeg fått det til å spille sånn noenlunde i JRuby.
class FriendshipTest < Test::Unit::TestCase
def test_basic_friendships
Person.transaction do
neo = Person.new(:first_name => "Neo")
assert_equal("Neo", neo.first_name)
morpheus = Person.new(:first_name => "Morpheus")
assert !neo.knows?(morpheus)
neo.meets(morpheus)
assert neo.knows?(morpheus)
end
end
end
Testene kjører, og dataene lagres i Neo4j-databasen. Grunnen til at jeg bare viser fram testkoden her er at jeg skrev den først, og implementasjonen derfor neppe vil imponere noen ennå. Det som er ganske kult er at Jruby er blitt modent nok til at man kan plukke fram et nytt og lovende javabibliotek og regne med at det kommer til å fungere i Jruby. Nå har jeg aldri vært spesielt glad i Java, men jeg merker at allerede etter en liten time med hacking i Ruby begynner et API å ta form som jeg kan like.
Der java-APIet for en transaksjon ser slik ut:
Transaction tx = Transaction.begin();
try
{
// all Neo operations that work with the node space, for example:
// Node firstNode = neo.createNode();
// ... etc ...
tx.success();
}
finally
{
tx.finish();
neo.shutdown();
}
... føles det mer Ruby-aktig å gjøre noe mer ActiveRecord-lignende i Ruby:
class Person
def self.transaction
@@neo = EmbeddedNeo.new("test")
tx = Transaction.begin
begin
yield
tx.success
rescue Exception => e
raise e
ensure
tx.finish
@@neo.shutdown
end
end
end
Dermed får man noe som ser ut som en transaksjon inn i Ruby-klassen sin:
Person.transaction do me = Person.new end
Har en sterk følelse av at dette ikke er siste gang vi skriver om Neo4j her…

Wow, cool stuff, in Ruby this gets even more slick than in Java. Is this something one could refer too from the meo4j site?
av Peter Neubauer, 12/05-2008
It isn’t exactly much to look at yet, but yeah, that would give another reason to get some more work done.
av Marius, 13/05-2008
Cool !
I have also been doing some meta programming with JRuby + Neo. I came up with the following API:
include Neo
start # Neo initialization …
perform do # perform in one transaction n1 = create_node n1.name=”n1 hopp” # you can set any property using this syntax
n1.traverse(:friend, stop_eval {|tp| tp.current_depth >= 1}, return_eval{ |tp| tp.current_node.name.include? “foo” }) do |node| puts “Found #{node.name}” end
endshutdown # Neo exists
av Andreas Ronge, 13/05-2008
Hi there, possibly you should subscribe to the https://lists.neo4j.org/mailman/listinfo/user list, discuss there to get some more input and get an SVN account and start working in https://svn.neo4j.org/laboratory/users/.
For the typing of nodes, there is the Neo meta component, that can impose type constraints and such stuff on nodes, see https://svn.neo4j.org/components/neo-meta/trunk/src/test/java/org/neo4j/neometa/model/TestOOModel.java
av Peter Neubauer, 13/05-2008
Object databases are indeed interesting. What is not obvious, however, is how to scale out a network database, which is designed as a single-machine embedded database. Since object relationships can’t straddle a network boundary, you end up in a single-machine prison. That’s not scaling :-)
Object databases have traditionally solved this problem with synchronous and/or asynchronous replication, the former guaranteeing integrity and the latter guaranteeing continuous availability (unfortunately, it has been mathematically proven that you can’t have both in a distributed environment).
But distributing a database doesn’t help much unless you also partition the database (if every machine as the entire database then every machine performs equally poorly), and for partitioning you might want some kind of <i>location-oriented</i> partitioning—you might want to put users on one box, comments on another, posts on another, and so on, and optimize access that way.
Oh, I don’t know — if you think legacy relational databases have messy schemas, what makes you think that a totally ad-hoc, unstructured database will look like after, say, 5 years of development? :-) When you put garbage in, you get garbage out. Technology is not a cure for bad habits, and this is ultimately a human problem.
However, I completely agree that un-/semi-structured databases provide more flexibility, especially when initially designing the app, where I prefer to be able to “sketch” as opposed to design.
av Alexander Staubo, 31/05-2008