ExpressとRethinkDBで作るRESTfulなWebAPIです。 RethinkDB公式のこちらを参考にしました。
ひとまず、Expressでルーティングを定義して、RethinkDB上のデータへのCRUD処理ができるところまで。
前提条件
- RethinkDBをインストールしておく。
- Express起動前にローカルでRethinkDBを立ち上げておく。
パッケージ
"async": "^2.0.1", "body-parser": "^1.15.2", "express": "^4.14.0", "rethinkdb": "^2.3.3"
config
// ./config.js module.exports = { rethinkdb: { host: 'localhost', port: 28015, authKey: '', db: 'rethinkdb_ex' }, express: { port: 3000 } }
本体
雑なベタ貼りですみません…。都度コメント書いてあります。 ポイントとして、ReQLの実行結果はプロミスが返ります。
// ./server.js const r = require('rethinkdb') const express = require('express') const async = require('async') const bodyParser = require('body-parser') const config = require(__dirname + '/config') const app = express() // index.htmlとその他のフロントエンドアセットをサーブする。 app.use(express.static(__dirname + '/public')) app.use(bodyParser.json()) /* * すべてのTodoアイテムを取得 */ const listTodoItems = (req, res, next) => { r.table('todos').orderBy({index: 'createdAt'}).run(req.app._rdbConn, (err, cursor) => { if(err) { return next(err) } cursor.toArray((err, result) => { if(err) { return next(err) } res.json(result) }) }) } /* * 新しくTodoを作成してinsert */ const createTodoItem = (req, res, next) => { const todoItem = req.body todoItem.createAt = r.now() console.dir(todoItem) r.table('todos').insert(todoItem, {returnChanges: true}).run(req.app._rdbConn, (err, result) => { if(err) { return next(err) } res.json(result.changes[0].new_val) }) } /* * 特定のTodoを取得 */ const getTodoItem = (req, res, next) => { const todoItemID = req.params.id r.table('todos').get(todoItemID).run(req.app._rdbConn, (err, result) => { if(err) { return next(err) } res.json(result) }) } /* * Todoの更新 */ const updateTodoItem = (req, res, next) => { const todoItem = req.body const todoItemID = req.params.id r.table('todos').get(todoItemID).update(todoItem, {returnChanges: true}).run(req.app._rdbConn, (err, result) => { if(err) { return next(err) } res.json(result.changes[0].new_val) }) } /* * Todoの削除 */ const deleteTodoItem = (req, res, next) => { const todoItemID = req.params.id r.table('todos').get(todoItemID).delete().run(req.app._rdbConn, (err, result) => { if(err) { return next(err) } res.json({success: true}) }) } /* * page-not-found ミドルウェア */ const handle404 = (req, res, next) => { res.status(404).end('not found') } /* * 500ページを送り返し、エラーをロギングする */ const handleError = (err, req, res, next) => { console.error(err.stack) res.status(500).json({err: err.message}) } /* * DB接続をストアして、ポートのリッスンを始める */ const startExpress = (connection) => { app._rdbConn = connection app.listen(config.express.port) console.log(`Listening on port ${config.express.port}`) } // ルーティング定義 app.route('/todos') .get(listTodoItems) .post(createTodoItem) app.route('/todos/:id') .get(getTodoItem) .put(updateTodoItem) .delete(deleteTodoItem) app.use(handle404) app.use(handleError) /* * RethinkDBに接続して、必要なテーブルを作成してインデックスを貼り、expressを起動する */ async.waterfall([ // RethinkDBに接続 function connect(callback) { r.connect(config.rethinkdb, callback) }, // DBを無ければ作成 function createDatabase(connection, callback) { r.dbList().contains(config.rethinkdb.db).do((containsDb) => { return r.branch( containsDb, {created: 0}, r.dbCreate(config.rethinkdb.db) ) }).run(connection, (err) => { callback(err, connection) }) }, // テーブルを無ければ作成 function createTable(connection, callback) { r.tableList().contains('todos').do((containsTable) => { return r.branch( containsTable, {created: 0}, r.tableCreate('todos') ) }).run(connection, (err) => { callback(err, connection) }) }, // インデックスが無ければ作成 function createIndex(connection, callback) { r.table('todos').indexList().contains('createdAt').do((hasIndex) => { return r.branch( hasIndex, {created: 0}, r.table('todos').indexCreate('createdAt') ) }).run(connection, (err) => { callback(err, connection) }) }, // インデックスをwaitさせる function waitForIndex(connection, callback) { r.table('todos').indexWait('createdAt').run(connection, (err, result) => { callback(err, connection) }) } ], (err, connection) => { if(err) { console.error(err) process.exit(1) return } // express起動 startExpress(connection) })
このスクリプトを、$ node server.js
で起動します。
様子
左がAdvanced REST clientというクロームAppで、HTTPリクエストを送信しています。右がRethinkDBのAdmin画面で、データの変更を検知できます。