Einführung in das Ruby-Interface zur NOSql-Datenbank ArcadeDB.
Gemfile
gem 'arcadedb', git: "https://github.com/topofocus/arcadedb"
gem 'arcade-time-graph', git: "https://github.com/topofocus/arcade-time-graph"
Skript
require 'arcade'
require 'arcade-time-graph'
ProjectRoot = Pathname.new( Dir.pwd ).parent # Location der Config-Datei
Arcade::Init.connect
# Referenz zur Datenbank
db = Arcade::Init.db
# test
puts db.hierarchy type: :vertex
Config-Datei
---
:environment:
:test:
dbname: playground
user: root
pass: ***
:development:
dbname: hierondev
user: root
pass: ***
:production:
dbname: hieronymus
user: root
pass: ***
:admin:
:host: 10.247.8.109
:port: 2480
:user: root
:pass: ***
:logger: stdout # 'file' or 'stdout'
:namespace: Arcade # Default Namespace
:autoload: true # load model if a link is detected in a record
ArcadeDB ist eine universale NOSql-Datenbank. »NOSql« steht für »Not Only Sql«. Sie kann also mehr als Sql-Datenbankabfragen
Die Daten können als Graphen organisiert werden. Die Daten sind in Vertices gespeichert, die über Edges verbunden sind. Alternativ werden sie über Schlüssel abgespeichert (Key/Value). Zuletzt können die Daten in lose strukturierten Dokumenten organisiert werden. Alle denkbaren Hybridlösungen werden natürlich unterstützt. Die Datenbank verwendet Standardprotokolle für die Datenzugriffe.
Modelfiles
In einem model
-Verzeichnis wird (analog zu Rails) Ruby-seitig die Datenstruktur definiert.
In den Model-Files werden Ruby-Model-Objektklassen und die korrespondierenden Datenbank-Types definiert.
Falls erforderlich können Datenbank-Objekte strikt definiert werden. Wenn Indizes definiert werden, ist eine
strikte Definition der Datenbank nötig.
Hier ein Beispiel für die Definition einer Person
module Arcade
class Person
attribute :name, Types::Nominal::String
attribute :surname, Types::Nominal::String.default( "".freeze )
attribute :email?, Types::Email
attribute :age?, Types::Nominal::Integer
attribute :active, Types::Nominal::Bool.default( true )
attribute :conterfeil?, Types::Nominal::Any
def self.db_init
File.read(__FILE__).gsub(/.*__END__/m, '')
end
end
end
## The code below is executed on the database after the database-type is created
## Use the output of `ModelClass.database_name` as DB type name
##
__END__
CREATE PROPERTY user.name STRING
CREATE PROPERTY user.surname STRING
CREATE PROPERTY user.email STRING
CREATE INDEX ON user ( name ) NOTUNIQUE
CREATE INDEX ON user ( name, surname, email ) UNIQUE
Die Definitionen sind weitgehend selbsterklärend. Attribute mit einem Fragezeichen sind optional. Die Daten sind streng typisiert, das ist Voraussetzung für einen konsistenten Datenbankaufbau.
Die Datenbankdefinition wird beim Programmstart eingelesen.
Person.create_type
überträgt die Definition von Attributen (Properties) und Indizes an
zur Datenbank.
Adhoc Datenbank
Zusätzlich zu definierten Datenbankfeldern können weitere, untypisierte Felder angelegt werden.
So können dynamisch unidirektionale Abhängigkeiten adhoc dargestellt werden:
Person.create name: 'Hugo', surname: 'Gans'
father: Person.create( name: 'Otto', surname: 'Gans' ),
children: [ "Eva", "Ulli", "Uwe",
"Georg" ].map do |c|
Person.create name: c, surname: 'Gans'
end
Diese Anweisung legt father
und children
-Felder an und füllt sie mit Personen. Die Ausgabe des Datensatzes
zeigt die angelegten Personen in Form ihrer Datenbank-Identitäten.
puts hugo.to_human
<person[#187:0]: active: true,
children: ["#175:0", "#178:0", "#181:0", "#184:0"],
father: <person[#172:0]: active : true, name : Otto, surname : Gans>,
name: Hugo, surname: Gans>
puts hugo.children.map &:expand
<person[#175:0]: active : true, name : Eva, surname : Gans>
<person[#178:0]: active : true, name : Ulli, surname : Gans>
<person[#181:0]: active : true, name : Uwe, surname : Gans>
<person[#184:0]: active : true, name : Georg, surname : Gans>