ArangoDBはスキーマフリーでMongoDBやCouchDBと比較されることが多いデータベースです。グラフも扱えるということで、試しに使ってみました。
インストール
主要なOSについては、インストーラもしくはパッケージが用意されています。今回はUbuntu12.04にパッケージをインストールしました。
| 1 2 3 4 5 | $ sudo echo 'deb http://www.arangodb.org/repositories/stable/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/arangodb.list $ wget http://www.arangodb.org/repositories/stable/xUbuntu_12.04/Release.key $ sudo apt-key add - < Release.key $ apt-get update $ apt-get install arangodb | 
インストール後、起動してデフォルトで8529番ポートで待ち受けます。
CRUD
ArangoDBもMongoDBなどのドキュメント指向DB同様、RDBのテーブルに相当するものをコレクション、レコードに相当するものをドキュメントと呼んでいます。
Webのインターフェイス(http://localhost:8529/)もありますが、arangoshを使ってデータを操作してみます。arangoshを起動すると、パスワードを聞かれますが、設定を変更していなければノーパスでログインできます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | $ arangosh     Please specify a password:                                         _        __ _ _ __ __ _ _ __   __ _  ___  ___| |__    / _` | '__/ _` | '_ \ / _` |/ _ \/ __| '_ \  | (_| | | | (_| | | | | (_| | (_) \__ \ | | |  \__,_|_|  \__,_|_| |_|\__, |\___/|___/_| |_|                        |___/                  Welcome to arangosh 1.3.3. Copyright (c) triAGENS GmbH Using Google V8 3.16.14 JavaScript engine, READLINE 6.2, ICU 4.8.1.1 Connected to ArangoDB 'tcp://localhost:8529' version 1.3.3 ------------------------------------- Help ------------------------------------- Predefined objects:                                                    arango:                                ArangoConnection              db:                                    ArangoDatabase              Example:                                                              > db._collections();                    list all collections         > db.<coll_name>.all().toArray();       list all documents           > id = db.<coll_name>.save({ ... });    save a document              > db.<coll_name>.remove(<_id>);         delete a document            > db.<coll_name>.document(<_id>);       get a document               > db.<coll_name>.replace(<_id>, {...}); overwrite a document         > db.<coll_name>.update(<_id>, {...});  partially update a document  > help                                  show help pages              > exit                                                              Note: collection names may be cached in arangosh. To refresh them, issue:   > db._collections();                                                arangosh>  | 
まず、コレクションを作成。
| 1 2 | arangosh> db._create("example"); [ArangoCollection 23182034, "example" (type document, status loaded)] | 
作成したコレクションにドキュメントを登録。
| 1 2 3 4 5 6 7 8 | arangosh> db.example.save({hello:"world"}); { "error" : false, "_id" : "example/24361682", "_rev" : "24361682", "_key" : "24361682" } arangosh> db.example.save({name:"taro", age:30 });  { "error" : false, "_id" : "example/24689362", "_rev" : "24689362", "_key" : "24689362" } arangosh> db.example.save({name:"hanako", age:25 });  { "error" : false, "_id" : "example/24820434", "_rev" : "24820434", "_key" : "24820434" } | 
登録したレコードを取り出してみます。start_pretty_print()は結果を整形して出力するためのコマンドです。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | arangosh> start_pretty_print(); using pretty printing arangosh> db.example.all().toArray(); [    {      "_id" : "example/24689362",      "_rev" : "24689362",      "_key" : "24689362",      "age" : 30,      "name" : "taro"    },    {      "_id" : "example/24361682",      "_rev" : "24361682",      "_key" : "24361682",      "hello" : "world"    },    {      "_id" : "example/24820434",      "_rev" : "24820434",      "_key" : "24820434",      "age" : 25,      "name" : "hanako"    }  ] | 
ドキュメントをIDで取り出してみます。IDで取り出す場合は、ドキュメントが返ってきますのでtoArray()なして表示されます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | arangosh> db.example.document("24689362"); {    "age" : 30,    "name" : "taro",    "_id" : "example/24689362",    "_rev" : "24689362",    "_key" : "24689362"  } arangosh> db._document("example/24689362"); {    "age" : 30,    "name" : "taro",    "_id" : "example/24689362",    "_rev" : "24689362",    "_key" : "24689362"  } | 
属性に一致するドキュメントの取り出し。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | arangosh> db.example.byExample({name:"taro"}).toArray(); [    {      "_id" : "example/24689362",      "_rev" : "24689362",      "_key" : "24689362",      "age" : 30,      "name" : "taro"    }  ] arangosh> db.example.byExample({name:"jiro"}).toArray(); [ ] | 
より複雑な条件で検索するにはAQLという問い合わせ言語使います。AQLの詳しい文法はこちら。
| 1 2 3 4 5 6 7 8 9 10 | arangosh> db._query('FOR user IN example FILTER user.age >=30 RETURN user').toArray(); [    {      "_id" : "example/24689362",      "_rev" : "24689362",      "_key" : "24689362",      "age" : 30,      "name" : "taro"    }  ] | 
ドキュメントの更新。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | arangosh> a1 = db._document("example/24689362"); {    "age" : 30,    "name" : "taro",    "_id" : "example/24689362",    "_rev" : "24689362",    "_key" : "24689362"  } arangosh> db.example.update(a1, {name:"jiro",age:30}); {    "error" : false,    "_id" : "example/24689362",    "_rev" : "23718554346",    "_key" : "24689362"  } arangosh> db.example.toArray(); [    {      "_id" : "example/24689362",      "_rev" : "23718554346",      "_key" : "24689362",      "age" : 30,      "name" : "jiro"    },    {      "_id" : "example/24361682",      "_rev" : "24361682",      "_key" : "24361682",      "hello" : "world"    },    {      "_id" : "example/24820434",      "_rev" : "24820434",      "_key" : "24820434",      "age" : 25,      "name" : "hanako"    }  ] | 
ドキュメントの削除。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | arangosh> a1 = db._document("example/24689362"); {    "age" : 30,    "name" : "jiro",    "_id" : "example/24689362",    "_rev" : "23718554346",    "_key" : "24689362"  } arangosh> db.example.remove(a1); true arangosh> db.example.toArray(); [    {      "_id" : "example/24361682",      "_rev" : "24361682",      "_key" : "24361682",      "hello" : "world"    },    {      "_id" : "example/24820434",      "_rev" : "24820434",      "_key" : "24820434",      "age" : 25,      "name" : "hanako"    }  ] | 
データのインポート
もう少し大きなデータを入れて検索してみます。こちらのサンプルデータを使います。いくつかサンプルデータがありますが、主要都市の緯度経度の情報を登録してみます。レコード数は約30万件です。
インポートできるのはjson, csv, tsv(タブ区切り)の3種類で、csvとtsvは属性名を1行目に入れて、データは2行目から始めます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | arangoimp --file GeoLiteCity.csv --collection=cities --create-collection=true --type=csv Please specify a password:  Connected to ArangoDB 'tcp://127.0.0.1:8529' Version 1.3.3 ---------------------------------------- collection:       cities create:           yes file:             GeoLiteCity.csv type:             csv quote:            " separator:        , connect timeout:  3 request timeout:  300 ---------------------------------------- Starting CSV import... created:          316848 errors:           0 total:            316849 | 
検索の注意点
上で登録したデータから”Tokyo”を抜き出してみます。このとき、byExample()による検索とAQLによる検索ができますが、それぞれ所要時間を計測してみます。
byExample()による検索
| 1 2 | arangosh> d = new Date();ts=d.getTime();db.cities.byExample({name:"Tokyo"}).toArray();d = new Date();te=d.getTime();print(te - ts); 96 | 
AQLによる検索
| 1 2 | arangosh> d = new Date();ts=d.getTime();db._query('FOR city IN cities FILTER city.city == "Tokyo" RETURN city').toArray();d = new Date();te=d.getTime();print(te - ts); 1903 | 
byExample()では96msecのところが、AQLでは1903msecと大きな開きがあります。AQLを使わなくても済むところでは、AQLは使わないのが鉄則です。
ちなみにMySQLでキャッシュを無効にして試したところ、140msecでした。
次回は”edge”と呼ばれる特殊なドキュメントについてみていく予定です。
おまけ
最初のほうでWebのインターフェイスもあると書きましたが、Webのインターフェイスは、http://localhost:8529/にアクセスすれば使えます。


 
            