[ざっくり] DocumentDB Node.jsで使う。 AWS DynamoDBとの比較も

みなさんこんにちは。最近はAzureにどっぷりです。
今日は、AzureのNoSQLデータベースサービスである、DocumentDBを、node.jsから使ってみたいと思います。


# DocumentDBとは？
DocumentDBは、ドキュメント型NoSQLに区分される、jsonドキュメントを格納するためのデータベースです。
同じドキュメント型のNoSQLとしては、 AWS DynamoDBが挙げられます。
DocumentDBは、NoSQL(Not only sql)ですが、<b>SQLが使えます</b>。
NoSQLの詳しい説明については、既に色々な記事で書かれていますので、ここでは割愛します。

# Azure DocumentDB vs AWS DynamoDB
DocumentDBは、SQLでドキュメントをクエリ出来て、何の設定もしなくてもドキュメントがソートできてしまいます。
DynamoDBで同じことをやろうとすると、DynamoDB独特の書き方を学習したり、レンジキーを設定したりと、色々やらなければいけないことがあるのですが、DocumentDBでは、慣れ親しんだSQLをほぼそのまま書くことで対応できてしまいます。
これは衝撃的でした。

コードで比較してみましょう。
まずはAWS DynamoDBから。

### DynamoDBにおけるドキュメント取得とフィルタリング
```javascript
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();

var params = {
    TableName: "FileUploadLog",
    ProjectionExpression: "#ts, Filename",
    FilterExpression: "#ts between : start_date and : end_date",
    ExpressionAttributeNames: {
        "#ts": "TimeStamp",
    },
    ExpressionAttributeValues: {
         ":start_date": "2016-10-10 00:00:00",
         ":end_date": "2016-10-15 00:00:00" 
    }
};

docClient.scan(params, onScan);

function onScan(err, data) {
    if (err) {
        console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
    } else {
        // print all the movies
        console.log("Scan succeeded.");
        data.Items.forEach(function(log) {
           console.log(JSON.stringify(log));
        });

        // continue scanning if we have more movies
        if (typeof data.LastEvaluatedKey != "undefined") {
            console.log("Scanning for more...");
            params.ExclusiveStartKey = data.LastEvaluatedKey;
            docClient.scan(params, onScan);
        }
    }
}
```
docClient.scanの結果がコールバックに返され、次のデータ取得用のキー（LastEvaluatedKey）が入っていたら、それをExclusiveStartKeyに指定して、またscanを実行する、という方法です。
時刻などでアイテムをフィルタリングする場合は、FilterExpressionに条件を指定します。

では次にDocumentDBの方を見ていきましょう。

### DocumentDBにおけるドキュメント取得とフィルタリング
```javascript
var TaskDao = require("./taskDao"); //DocumentDB wrapper

var config = {};
config.host = "YOUR_DOCUMENTDB_HOST_ADDRESS";
config.authKey = "YOUR_AUTH_KEY";
config.databaseId = "YOUR_DATABASE_ID";
config.collectionId = "YOUR_COLLECTION_ID";


var DocumentDBClient = require("documentdb").DocumentClient;
var docDbClient = new DocumentDBClient(config.host, {
    masterKey: config.authKey
});

var taskDao = new TaskDao(docDbClient, config.databaseId, config.collectionId);


new Promise((resolve, reject) => {
    taskDao.init((err) => {
        if (err) {
            reject(err);
            return;
        }
        resolve();
    });
})
.then((data) => {
    console.log("data: ");
    console.log(JSON.stringify(data));
    return new Promise((resolve, reject) => {

        var querySpec = {
            query: "SELECT TOP @limit * FROM root r WHERE r.TimeStamp BETWEEN @start_date AND @end_date",
            parameters: [{
                name: "@limit",
                value: 10
            },{
                name: "@start_date",
                value: "2016-10-15 00:00:00"
            },{
                name: "@end_date",
                value: "2016-10-20 00:00:00"
            }]
        };

        taskDao.find(querySpec, function (err, items) {
            if (err) {
                reject(err);
                return;
            }

            resolve(items);
        });

    });
})
.then((data) => {
    console.log("data :");
    console.log(JSON.stringify(data));
})
.catch((err) => {
    console.log("err :");
    console.log(JSON.stringify(err));
});
```
なんと普通に`SELECT *` できてしまいます。これは非常に簡単ですね。
ソートも簡単です。最新１０件取得ならこんなクエリを発行すれば良いです。

```SQL
SELECT TOP 10 * FROM root r ORDER BY r.TimeStamp DESC
```
DocumentDBでは`ORDER BY`句で普通にソート出来てしまいました。
DocumentDBのこの柔軟さはかなり使い勝手の面でアドバンテージが大きいと思います。成果物の完成スピードが段違いに早くなりますね。

# まとめ
今日はDocumentDBをNode.jsから使ってみました。
AWS DynamoDBと比較すると、使い勝手の面でかなりの差があることがわかります。
もちろん、性能・価格・柔軟性、色々なファクターがありますので、１軸で評価し甲乙を付けることは出来ませんが、SQLで簡単にデータ検索、フィルタリング、ソートが出来てしまうのは、かなり魅力的なんではないでしょうか。
Azureのサービスの中でもとりわけお勧めしたいサービスです。

# 参考記事
実装に際して、下記の記事を参考にさせていただきました。
Node.js ExpressからDocumentDBを扱う方法が、サンプルコードと共に示されているので、とても分かりやすいです。
本記事中で使用している、DocumentDBのラッパー`taskDao`の実装も載っています。
https://docs.microsoft.com/ja-jp/azure/documentdb/documentdb-nodejs-application