MongoDB への Node.js 接続

Node.js が MySQL に接続する なし

MongoDB は、C++ で書かれたドキュメント指向のデータベース管理システムです。

この章では、Node.js を使用して MongoDB に接続し、データベースを操作する方法を紹介します。

ドライバーをインストールします

$ cnpm install mongodb

次に、追加、削除、変更、確認の機能を実装しましょう。

データベースの作成

MongoDB でデータベースを作成するには、まず MongoClient オブジェクトを作成し、次に指定された URL とポート番号を構成する必要があります。

データベースが存在しない場合、MongoDB はデータベースを作成し、接続を確立します。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/runoob";
 
MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  console.log("データベースが作成されました!");
  db.close();
});

コレクションの作成

createCollection() メソッドを使用してコレクションを作成できます。

var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/runoob';
MongoClient.connect(url, function (err, db) {
    if (err) throw err;
    console.log('データベースが作成されました');
    var dbase = db.db("runoob");
    dbase.createCollection('site', function (err, res) {
        if (err) throw err;
        console.log("コレクションを作成する!");
        db.close();
    });
});

データベース操作 ( CURD )

MySQL とは異なり、MongoDB はデータベースとコレクションを自動的に作成するため、使用する前に手動で作成する必要はありません。

データを挿入

次の例では、データベース runoob のサイト テーブルに接続し、insertOne() を使用してデータを挿入します。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3c");
    var myobj = { name: "html", url: "w3cstudy.cc" };
    dbo.collection("site").insertOne(myobj, function(err, res) {
        if (err) throw err;
        console.log("ドキュメントが正常に挿入されました");
        db.close();
    });
});

次のコマンドを実行すると、出力は次のようになります:

$ node test.js
ドキュメントが正常に挿入されました

出力結果を見ると、データは正常に挿入されています。

次のように、MongoDB クライアントを開いてデータを表示することもできます。

> show dbs
runoob  0.000GB          # w3c データベースが自動的に作成されました
> show tables
site                     # siteコレクション(データテーブル)を自動作成
> db.site.find()
{ "_id" : ObjectId("5a794e36763eb821b24db854"), "name" : "html", "url" : "w3cstudy.cc" }
> 

複数のデータを挿入する場合は、insertMany() を使用できます。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    var myobj =  [
        { name: 'html', url: 'https://w3cstudy.cc', type: 'cn'},
        { name: 'Google', url: 'https://www.google.com', type: 'en'},
        { name: 'Facebook', url: 'https://www.google.com', type: 'en'}
       ];
    dbo.collection("site").insertMany(myobj, function(err, res) {
        if (err) throw err;
        console.log("挿入されたドキュメントの数は次のとおりです: " + res.insertedCount);
        db.close();
    });
});

res.insertedCount は、挿入された項目の数です。

データのクエリ

find() を使用してデータを検索でき、find() は条件に一致するすべてのデータを返すことができます。 条件が指定されていない場合、find() はコレクション内のすべてのデータを返します。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    dbo.collection("site"). find({}).toArray(function(err, result) { // コレクション内のすべてのデータを返します
        if (err) throw err;
        console.log(result);
        db.close();
    });
});

次の例では、「html」という名前のインスタンスを取得します。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
     var whereStr = {"name":'html'};  // クエリ条件
    dbo.collection("site").find(whereStr).toArray(function(err, result) {
        if (err) throw err;
        console.log(result);
        db.close();
    });
});

次のコマンドを実行すると、出力は次のようになります:

[ { _id: 5a794e36763eb821b24db854,
    name: 'html',
    url: 'https://w3cstudy.cc' } ]

データを更新

データベース内のデータを変更することもできます。次の例では、「html」という名前の URL を https://w3cstudy.cc/ に変更します。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    var whereStr = {"name":'html'};  // クエリ条件
    var updateStr = {$set: { "url" : "https://w3cstudy.cc/" }};
    dbo.collection("site").updateOne(whereStr, updateStr, function(err, res) {
        if (err) throw err;
        console.log("ドキュメントが正常に更新されました");
        db.close();
    });
});

実行が成功したら、mongo 管理ツールを起動して、データが変更されたことを確認します。

> db.site.find().pretty()
{
    "_id" : ObjectId("5a794e36763eb821b24db854"),
    "name" : "html",
    "url" : "https://w3cstudy.cc/"     
}

条件を満たすすべてのドキュメント データを更新する場合は、updateMany() を使用できます。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    var whereStr = {"type":'en'};  //クエリ条件
    var updateStr = {$set: { "url" : "https://w3cstudy.cc/" }};
    dbo.collection("site").updateMany(whereStr, updateStr, function(err, res) {
        if (err) throw err;
         console.log(res.result.nModified + "ドキュメントが更新されました");
        db.close();
    });
});

result.nModified は更新されたアイテムの数です。

データの削除

次の例では、「html」という名前のデータを削除します。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    var whereStr = {"name":'html'};  // クエリ条件
    dbo.collection("site").deleteOne(whereStr, function(err, obj) {
        if (err) throw err;
        console.log("ドキュメントは正常に削除されました");
        db.close();
    });
});

実行が成功したら、mongo 管理ツールに入り、データが削除されたことを確認します。

> db.site.find()
> 

複数のステートメントを削除する場合は、deleteMany() メソッドを使用できます。

次の例では、タイプが en であるすべてのデータを削除します。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    var whereStr = { type: "en" };  // クエリ条件
    dbo.collection("site").deleteMany(whereStr, function(err, obj) {
        if (err) throw err;
        console.log(obj.result.n + "ドキュメントが削除されました");
        db.close();
    });
});

obj.result.n 削除されたアイテムの数。

並べ替え

並べ替え sort() メソッドを使用します。このメソッドは、昇順 (1) または降順 (-1) を指定するパラメータを受け取ります。

例:

{ type: 1 } // type フィールドによる昇順
{ type: -1 } //type フィールドによる降順

type の昇順で並べ替えます:

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    var mysort = { type: 1 };
    dbo.collection("site").find().sort(mysort).toArray(function(err, result) {
        if (err) throw err;
        console.log(result);
        db.close();
    });
});	

クエリページ

返されるアイテムの指定数を設定する場合は、limit() メソッドを使用できます。このメソッドは、返されるアイテムの数を指定するパラメータを 1 つだけ受け入れます。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    dbo.collection("site").find().limit(2).toArray(function(err, result) {
        if (err) throw err;
        console.log(result);
        db.close();
  });
});

スキップする項目の数を指定する場合は、skip() メソッドを使用できます。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
    dbo.collection("site").find().skip(2).limit(2).toArray(function(err, result) {
        if (err) throw err;
        console.log(result);
        db.close();
  });
});

接続操作

mongoDB はリレーショナル データベースではありませんが、$lookup を使用して左結合を実現できます。

たとえば、次の 2 つのデータ セットがあります。

コレクション 1: 注文

[
  { _id: 1, product_id: 154, status: 1 }
]

集合2:products

[
  { _id: 154, name: 'ラップトップ' },
  { _id: 155, name: 'ヘッドフォン' },
  { _id: 156, name: 'デスクトップ コンピューター' }
]

$lookup は左結合を実装します

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://127.0.0.1:27017/";
 
MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  var dbo = db.db("w3cstudy");
  dbo.collection('orders').aggregate([
    { $lookup:
       {
         from: 'products',            // 正しいコレクション
         localField: 'product_id',    // コレクション join フィールドを残します
         foreignField: '_id',         // 正しいコレクション join フィールド
         as: 'orderdetails'           // 新しく生成されたフィールド (array 型)
       }
     }
    ]).toArray(function(err, res) {
    if (err) throw err;
    console.log(JSON.stringify(res));
    db.close();
  });
});

コレクションを削除

drop() メソッドを使用してコレクションを削除できます。

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
 
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("w3cstudy");
 // test コレクションを削除します
    dbo.collection("test").drop(function(err, delOK) { // 正常に実行された場合、delOK は true を返し、それ以外の場合は false を返します。
        if (err) throw err;
        if (delOK) console.log("コレクションが削除されました");
        db.close();
    });
});

Promise の使用

Promise は、複雑な非同期タスクをよりエレガントに記述するために ECMAScript 6 によって提供されるクラスです。

次の例では、Promise を使用してコレクションを作成します。

const MongoClient = require("mongodb").MongoClient;
const url = "mongodb://localhost/w3cstudy";
MongoClient.connect(url).then((conn) => {
    console.log("データベースが接続されました");
    var dbase = conn.db("w3cstudy");
    dbase.createCollection("site").then((res) => {
        console.log("コレクションが作成されました");
    }).catch((err) => {
        console.log("データベース操作エラー");
    }).finally(() => {
        conn.close();
    });
}).catch((err) => {
    console.log("データベース接続に失敗しました");
});

Promise データ操作

次に、1 つのプログラムに 4 つの連続した操作 (add 、 query 、change 、 delete ) を実装します。

const MongoClient = require("mongodb").MongoClient;
const url = "mongodb://localhost/";
MongoClient.connect(url).then((conn) => {
    console.log("データベースが接続されました");
    const test = conn.db("testdb").collection("test");
    //増加
    test.insertOne({ "site": "w3cstudy.cc" }).then((res) => {
        //お問い合わせ
        return test.find().toArray().then((arr) => {
            console.log(arr);
        });
    }).then(() => {
        // 変化
        return test.updateMany({ "site": "w3cstudy.cc" },
            { $set: { "site": "example.com" } });
    }).then((res) => {
        // お問い合わせ
        return test.find().toArray().then((arr) => {
            console.log(arr);
        });
    }).then(() => {
        //消去
        return test.deleteMany({ "site": "example.com" });
    }).then((res) => {
        //お問い合わせ
        return test.find().toArray().then((arr) => {
            console.log(arr);
        });
    }).catch((err) => {
        console.log("データ操作に失敗しました" + err.message);
    }).finally(() => {
        conn.close();
    });
}).catch((err) => {
    console.log("データベース接続に失敗しました");
});

実行結果:

データベースが接続されました
[ { _id: 5f1664966833e531d83d3ac6, site: 'w3cstudy.cc' } ]
[ { _id: 5f1664966833e531d83d3ac6, site: 'example.com' } ]
[]

非同期関数を使用して同じデータ操作を実現

const MongoClient = require("mongodb").MongoClient;
const url = "mongodb://localhost/";
 
async function dataOperate() {
    var conn = null;
    try {
        conn = await MongoClient.connect(url);
        console.log("データベースが接続されました");
        const test = conn.db("testdb").collection("test");
        // 増加
        await test.insertOne({ "site": "w3cstudy.cc" });
        // お問い合わせ
        var arr = await test.find().toArray();
        console.log(arr);
        // 変化
        await test.updateMany({ "site": "w3cstudy.cc" },
            { $set: { "site": "example.com" } });
        // お問い合わせ
        arr = await test.find().toArray();
        console.log(arr);
        // 消去
        await test.deleteMany({ "site": "example.com" });
        // お問い合わせ
        arr = await test.find().toArray();
        console.log(arr);
    } catch (err) {
        console.log("間違い:" + err.message);
    } finally {
        if (conn != null) conn.close();
    }
}
 
dataOperate();

操作結果:

データベースが接続されました
[ { _id: 5f169006a2780f0cd4ea640b, site: 'w3cstudy.cc' } ]
[ { _id: 5f169006a2780f0cd4ea640b, site: 'example.com' } ]
[]

結果はまったく同じです。

明らかに、非同期関数は非常に優れたプログラミング スタイルであり、非同期操作を何度も使用する場合に非常に実用的です。

ただし、7.6.0 より前のバージョンの node.js では非同期関数を使用しないでください。