👌
ArangoDBのFoxxを始めるまで
ArangoDBとは
簡単に言えばDocument Database + Graph Database + Key/Value Store…まあNoSQL
Foxxとは
ArangoDBに組み込んで独自RestAPI提供できるシステム
始め方
をまとめた感じです
必要ファイルの用意
manifest.json
{
"engines": {
"arangodb": "^3.0.0"
},
"main": "index.js",
"scripts": {
"setup": "scripts/setup.js"
}
}
engines
でサポートするArangoDBのバージョン指定をする
main
で実行するプログラムとなる
scripts.setup
でセットアップ用プログラムとなる(ここで必要コレクション(=DBで言うところのテーブル)など作成する)
index.js
'use strict';
// joi 値チェック用ライブラリ
const joi = require('joi');
// ArangoDB使用するためのライブラリ
const db = require('@arangodb').db;
const errors = require('@arangodb').errors;
const foxxColl = db._collection('myFoxxCollection');
const DOC_NOT_FOUND = errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code;
const aql = require('@arangodb').aql;
// foxx用ルータ
const createRouter = require('@arangodb/foxx/router');
const router = createRouter();
module.context.use(router);
//===================================================================
// APIアクセス(/hello-world)
//===================================================================
router.get('/hello-world', function (req, res) {
res.send('Hello World2!');
})
.response(['text/plain'], 'A generic greeting.')
.summary('Generic greeting')
.description('Prints a generic greeting.');
//===================================================================
// APIアクセス(/hello/:name)
//===================================================================
router.get('/hello/:name', function (req, res) {
res.send(`Hello ${req.pathParams.name}`);
})
.pathParam('name', joi.string().required(), 'Name to greet.')
.response(['text/plain'], 'A personalized greeting.')
.summary('Personalized greeting')
.description('Prints a personalized greeting.');
//===================================================================
// APIアクセス(/sum)
//===================================================================
router.post('/sum', function (req, res) {
const values = req.body.values;
res.send({
result: values.reduce(function (a, b) {
return a + b;
}, 0)
});
})
.body(joi.object({
values: joi.array().items(joi.number().required()).required()
}).required(), 'Values to add together.')
.response(joi.object({
result: joi.number().required()
}).required(), 'Sum of the input values.')
.summary('Add up numbers')
.description('Calculates the sum of an array of number values.');
// store schema in variable to make it re-usable, see .body()
const docSchema = joi.object().required().keys({
name: joi.string().required(),
age: joi.number().required()
}).unknown(); // allow additional attributes
//===================================================================
// APIアクセス(/entries)
//===================================================================
router.post('/entries', function (req, res) {
const multiple = Array.isArray(req.body);
const body = multiple ? req.body : [req.body];
let data = [];
for (var doc of body) {
const meta = foxxColl.save(doc);
data.push(Object.assign(doc, meta));
}
res.send(multiple ? data : data[0]);
})
.body(joi.alternatives().try(
docSchema,
joi.array().items(docSchema)
), 'Entry or entries to store in the collection.')
.response(joi.alternatives().try(
joi.object().required(),
joi.array().items(joi.object().required())
), 'Entry or entries stored in the collection.')
.summary('Store entry or entries')
.description('Store a single entry or multiple entries in the "myFoxxCollection" collection.');
//===================================================================
// APIアクセス(/entries/:key)
//===================================================================
router.get('/entries/:key', function (req, res) {
try {
const data = foxxColl.document(req.pathParams.key);
res.send(data)
} catch (e) {
if (!e.isArangoError || e.errorNum !== DOC_NOT_FOUND) {
throw e;
}
res.throw(404, 'The entry does not exist', e);
}
})
.pathParam('key', joi.string().required(), 'Key of the entry.')
.response(joi.object().required(), 'Entry stored in the collection.')
.summary('Retrieve an entry')
.description('Retrieves an entry from the "myFoxxCollection" collection by key.');
//===================================================================
// APIアクセス(/entries)
//===================================================================
router.get('/entries', function (req, res) {
const keys = db._query(aql`
FOR entry IN ${foxxColl}
RETURN entry._key
`);
res.send(keys);
})
.response(joi.array().items(
joi.string().required()
).required(), 'List of entry keys.')
.summary('List entry keys')
.description('Assembles a list of keys of entries in the collection.');
scripts/setup.js
'use strict';
// ArangoDB使用するためのライブラリ
const db = require('@arangodb').db;
const collectionName = 'myFoxxCollection';
// 指定コレクションがなければ作成する
if (!db._collection(collectionName)) {
db._createDocumentCollection(collectionName);
}
Zipでまとめる
manifest.json
とindex.js
とscripts/setup.js
をまとめたZipファイルを作る
※ここではindex.zipを作ったものとする
ArangoDBにindex.zipをアップする
http://arangodbのホスト:8529/
でArangoDB Web UIに入ってSERVICESをクリック&Add Serviceをクリック
左上にあるUploadをクリック
Drag & Drop Filesでindex.zipをドロップする&Installをクリック
ダイアログボックスが出るのでMount pointにアプリの名前を入れる(ここではmyfoxxとする)&Installを押す
myfoxxが登録される
myfoxxをクリックするとこのような画面になるので左上のAPIをクリック
index.jsでルータ定義したREST API一覧(Swagger)が出てくるのでAPIアクセス手法などがわかる
Discussion