Node.jsのpromiseでMongoDBを使用する方法は?


82

Node.jsでMongoDBを使用する方法を見つけようとしてきましたが、ドキュメントでは、コールバックを使用することをお勧めします。今、私はそれが好みの問題であることを知っていますが、私は本当に約束を使うことを好みます。

問題は、MongoDBでそれらを使用する方法が見つからなかったことです。確かに、私は以下を試しました:

var MongoClient = require('mongodb').MongoClient;

var url = 'mongodb://localhost:27017/example';

MongoClient.connect(url).then(function (err, db) {
    console.log(db);
});

そして結果はundefinedです。その場合、これはそうする方法ではないようです。

コールバックの代わりにpromiseを使用してNode内でmongodbを使用する方法はありますか?


guru99.com/node-js-promise-generator-event.htmlこのチュートリアルは間違っていますか?
Ravi Shanker Reddy 2017

回答:


118

あなたのアプローチはほぼ正しいです、あなたの議論のほんの小さな間違いです

var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017/example'
MongoClient.connect(url)
  .then(function (db) { // <- db as first argument
    console.log(db)
  })
  .catch(function (err) {})

11
丁度!MongoDB Node.jsドライバー2.x 「戻り値:コールバックが渡されなかった場合の約束」 iaby MongoClient.connect。ES6promiseが組み込まれていないnode.js <4がある場合は、ES6互換のpromise shimを使用するか、promiseLibraryオプションでES6互換のpromise実装を提供することもできますMongoClient.connect
VolkerM 2016

5
いくつかのテストに基づいて、mongodb//localhost:27017(データベースを指定せずに)URLに接続すると、mongoclientが返されるため、を呼び出す必要がありますmongoclient.db('example')mongodb.github.io/node-mongodb-native/api-generated/…を
PatS

21

async / awaitを実行することもできます

async function main(){
 let client, db;
 try{
    client = await MongoClient.connect(mongoUrl, {useNewUrlParser: true});
    db = client.db(dbName);
    let dCollection = db.collection('collectionName');
    let result = await dCollection.find();   
    // let result = await dCollection.countDocuments();
    // your other codes ....
    return result.toArray();
 }
 catch(err){ console.error(err); } // catch any mongo error here
 finally{ client.close(); } // make sure to close your connection after
}


私は今あなたの顔にキスすることができました。これは私が数時間で見つけた最も単純で最良の答えでした。
ロブE.

これは、最も単純で、最も新鮮で、最も完全で最新の可能な答えです。どうもありがとうございます。
keuluu

19

上記の回答のいずれも、bluebirdやq、またはその他の豪華なライブラリなしでこれを行う方法について言及していないので、これに2セントを追加しましょう。

ネイティブES6Promiseを使用して挿入を行う方法は次のとおりです

    'use strict';

const
    constants = require('../core/constants'),
    mongoClient = require('mongodb').MongoClient;



function open(){

    // Connection URL. This is where your mongodb server is running.
    let url = constants.MONGODB_URI;
    return new Promise((resolve, reject)=>{
        // Use connect method to connect to the Server
        mongoClient.connect(url, (err, db) => {
            if (err) {
                reject(err);
            } else {
                resolve(db);
            }
        });
    });
}

function close(db){
    //Close connection
    if(db){
        db.close();
    }
}

let db = {
    open : open,
    close: close
}

module.exports = db;

open()メソッドをpromiseを返すメソッドとして定義しました。挿入を実行するために、これが以下の私のコードスニペットです

function insert(object){
    let database = null;
    zenodb.open()
    .then((db)=>{
        database = db;
        return db.collection('users')    
    })
    .then((users)=>{
        return users.insert(object)
    })
    .then((result)=>{
        console.log(result);
        database.close();
    })
    .catch((err)=>{
        console.error(err)
    })
}



insert({name: 'Gary Oblanka', age: 22});

お役に立てば幸いです。これを改善するための提案があれば、私が自分自身を改善したいと思っているので、私に知らせてください:)


13
約束を別の約束で包みます。MongoClientメソッドはすでにpromiseを返しているので、これを再度ラップする必要はありません。これは典型的なプロミスアンチパターンです。
西部2016年

4
数か月後に登場しますが、元の投稿から20分後の@Greenの回答では、mongodb.MongoClientのネイティブpromiseサポートが使用されており、無関係なpromiseライブラリは使用されていません。
オーウェン

2
これは、サードパーティのPromiseライブラリに依存しないため、正解です。
GlGuru 2018

@westor新しいPromiseでラップせずに、open()メソッドからpromiseを返すにはどうすればよいですか?これが唯一の方法だと思います。
Abhishek Nalin 2018年

1
@AbhishekNalin MongoDB接続メソッド(少なくとも新しいバージョンでは)はpromiseを返します。したがって、単純に「mongoClient.connect(url).then(...)」と書くか、このopenメソッドでmongoClient.connect(url)を返します。あなたはコールバックを取り除くことができます。エラーケースは、ここで最後のキャッチによってキャッチされます。
西部2018年

11

これは、Node.jsでpromiseを使用してMongoDBを使用する方法の一般的な回答です。

コールバックパラメータが省略された場合、mongodbはpromiseを返します

Promiseに変換する前に

var MongoClient = require('mongodb').MongoClient,
dbUrl = 'mongodb://db1.example.net:27017';

MongoClient.connect(dbUrl,function (err, db) {
    if (err) throw err
    else{
        db.collection("users").findOne({},function(err, data) {
            console.log(data)
        });
    }
})

Promiseに変換した後

//converted
MongoClient.connect(dbUrl).then(function (db) {
    //converted
    db.collection("users").findOne({}).then(function(data) {
         console.log(data)
    }).catch(function (err) {//failure callback
         console.log(err)
    });
}).catch(function (err) {})

複数のリクエストを処理する必要がある場合

MongoClient.connect(dbUrl).then(function (db) {

   /*---------------------------------------------------------------*/

    var allDbRequest = [];
    allDbRequest.push(db.collection("users").findOne({}));
    allDbRequest.push(db.collection("location").findOne({}));
    Promise.all(allDbRequest).then(function (results) {
        console.log(results);//result will be array which contains each promise response
    }).catch(function (err) {
         console.log(err)//failure callback(if any one request got rejected)
    });

   /*---------------------------------------------------------------*/

}).catch(function (err) {})

1
接続後の操作のためにネストされたPromiseチェーンを作成するのはなぜですか?理由:MongoClient.connect(uri).then(client => client.db("db").collection("users").find()).then(data => console.log(data)).catch(err => console.log(err));
SerG 2018年

これは、ドキュメントへのリンクで良いだろう
mikemaccana

キャッチの短い表記:.catch(console.log)
ベンジャム

2

警告編集:

John Culvinerが指摘したように、この回答は非推奨です。ドライバーを使用してください、それは約束OOTBが付属しています。


bluebirdをpromiseライブラリとして使用することを選択した場合はpromisifyAll()、MongoClientでbluebirds関数を使用できます。

var Promise = require('bluebird');
var MongoClient = Promise.promisifyAll(require('mongodb').MongoClient);

var url = 'mongodb://localhost:27017/example';

MongoClient.connectAsync(url).then(function (db) {
    console.log(db);
}).catch(function(err){
    //handle error
    console.log(err);
});

6
MongoDBドライバーにはすでにpromiseがあります(bluebirdが必要な場合は、オプションで指定するか、global.Promiseにアタッチします)これは行わないでください!
John Culviner 2017年

2

パーティーに少し遅れていることは知っていますが、ES6を使用した例を共有したいと思います

const config = require('config');
const MongoClient = require('mongodb').MongoClient;

var _connection;
var _db;

const closeConnection = () => {
  _connection.close();
}

/**
 * Connects to mongodb using config/config.js
 * @returns Promise<Db> mongo Db instance
 */
const getDbConnection = async () => {
  if (_db) {
    return _db;
  }
  console.log('trying to connect');
  const mongoClient = new MongoClient(config.mongodb.url, { useNewUrlParser: true });
  _connection = await mongoClient.connect();
  _db = _connection.db(config.mongodb.databaseName);
  return _db;
}

module.exports = { getDbConnection, closeConnection };

ご覧になりたい場合は、ここでもう少し詳しく説明します。

https://medium.com/swlh/how-to-connect-to-mongodb-using-a-promise-on-node-js-59dd6c4d44a7


非常に素晴らしい。関数getDbConnectionは接続を返さないため、名前を変更するだけです。_dbを返します。:)
kroiz

1

次のような代替パッケージを使用するかmongodb-promisemongodbパッケージAPIを手動で約束するか、その周りに独自のPromiseを作成するか、次のようなPromiseユーティリティパッケージを使用することができます。bluebird.promisify


MongoDBドライバーにはすでにpromiseがあります(bluebirdが必要な場合は、オプションで指定するか、global.Promiseにアタッチします)これは行わないでください!
John Culviner 2017年

1

MongoDBバージョン> 3.0での作業ソリューション

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";


open = (url) => {
    return new Promise((resolve,reject) => {
        MongoClient.connect(url, (err,client) => { //Use "client" insted of "db" in the new MongoDB version
            if (err) {
                reject(err)
            } else {
                resolve({
                    client
                });
            };
        });
    });
};

create = (client) => {
    return new Promise((resolve,reject) => {
        db = client.db("myFirstCollection"); //Get the "db" variable from "client"
        db.collection("myFirstCollection").insertOne({
            name: 'firstObjectName',
            location: 'London'
            }, (err,result)=> {
                if(err){reject(err)}
                else {
                    resolve({
                        id: result.ops[0]._id, //Add more variables if you want
                        client
                    });
                }

            });
    });
};

close = (client) => {
    return new Promise((resolve,reject) => {
        resolve(client.close());
    })

};

open(url)
    .then((c) => {
        clientvar = c.client;
        return create(clientvar)
    }).then((i) => {
        idvar= i.id;
        console.log('New Object ID:',idvar) // Print the ID of the newly created object
        cvar = i.client
        return close(cvar)
    }).catch((err) => {
        console.log(err)
    })

0

Mongoに接続するpromiseを作成する必要があります。

次に、このpromiseを使用する関数を定義しますmyPromise.then(...)

例えば:

function getFromMongo(cb) {
    connectingDb.then(function(db) {

       db.collection(coll).find().toArray(function (err,result){
           cb(result);
       });

    });
}

ここに完全なコードがあります:

http://jsfiddle.net/t5hdjejg/


MongoDBドライバーにはすでにpromiseがあります(bluebirdが必要な場合は、オプションで指定するか、global.Promiseにアタッチします)これは行わないでください!
John Culviner 2017年

@JohnCulviner私が知る限り、.findは約束を返しませんか?一部のメソッドは実行します-たとえば、カーソル上の.count()は実行しますが、db.mycoll.find({})。thenは未定義ですか?
sil 2017年

@sil db.get( "collection")。find({something: "a"})。then()。catch(); 私のために働く
Rafique Mohammed 2018

0

これが接続を開くためのワンライナーです

export const openConnection = async ()  =>
     await MongoClient.connect('mongodb://localhost:27017/staticback')

このように呼んでください

const login = async () => 
const client = await openConnection()

-1

connectメソッドにpromiseインターフェースが定義されているようには見えません

http://mongodb.github.io/node-mongodb-native/2.1/tutorials/connect/

Mongodbコネクタライブラリにいつでも自分で実装できますが、それはおそらくあなたが探しているよりも複雑です。

本当にpromiseを操作する必要がある場合は、いつでもES6promiseポリフィルを使用できます。

https://github.com/stefanpenner/es6-promise

接続コードをそれでラップします。何かのようなもの

var MongoClient = require('mongodb').MongoClient;
var Promise = require('es6-promise').Promise;

var url = 'mongodb://localhost:27017/example';

var promise = new Promise(function(resolve, reject){
    MongoClient.connect(url, function (err, db) {
        if(err) reject(err);
        resolve(db);
    });        
});

promise.then(<resolution code>);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.