如何在Node.js中使用带有承诺的MongoDB?


82

我一直在尝试发现如何将MongoDB与Node.js一起使用,并且在文档中似乎建议的方法是使用回调。现在,我知道这只是一个优先事项,但我真的更喜欢使用诺言。

问题是我没有找到如何在MongoDB中使用它们。实际上,我已经尝试了以下方法:

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

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

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

结果是undefined。在那种情况下,看来这不是这样做的方法。

有什么方法可以在Node中使用带有promise而不是回调的mongo db?


Answers:


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 “返回:承诺如果没有回调传递” ia MongoClient.connect。如果您有没有内置ES6 Promise的node.js <4,那么您还可以使用ES6兼容的Promise垫片或通过的promiseLibrary选项提供ES6兼容的Promise实现MongoClient.connect
VolkerM 2013年

5
根据一些测试,如果您连接到URL mongodb//localhost:27017(未指定数据库),则会获得mongoclient,因此您需要致电mongoclient.db('example')。参见mongodb.github.io/node-mongodb-native/api-generated/…–
PatS

21

您还可以进行异步/等待

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
}


我现在可以亲吻你的脸。这是我几个小时内找到的最简单,最好的答案。
Rob E.

这只是最简单,最新鲜,最完整和最新的答案。非常感谢。
keuluu

19

由于以上答案均未提及如何在没有bluebird或q或其他任何精美的库的情况下执行此操作,因此,我在此添加2美分。

这是使用本机ES6 Promise进行插入的方法

    '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()方法定义为返回承诺的方法。要执行插入,这是我的以下代码段

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,因此无需再次包装它。这是典型的承诺反模式。
Westor

4
几个月后,但是@Green在原始帖子的20分钟后回答使用mongodb.MongoClient的本机Promise支持,没有多余的Promise库。
欧文

2
这应该是正确的答案,因为它不依赖于任何第三方promise库。
GlGuru

@westor您如何从open()方法返回一个承诺而不将其包装在新的Promise中?我认为这是唯一的方法。
Abhishek Nalin

1
@AbhishekNalin MongoDB connect方法(至少在较新版本中)返回承诺。因此,您可以简单地编写“ mongoClient.connect(url).then(...)”,或者在此打开方法中,您将返回mongoClient.connect(url)。您可以摆脱回调。错误情况由此处的最后一个捕获捕获。
6

11

这是有关如何在Node.js中将MongoDB与Promise一起使用的一般答案

如果省略了回调参数,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

使用文档链接会更好
mikemaccana

捕获的简称:.catch(console.log)
杰姆

2

警告编辑:

正如约翰·库尔维纳(John Culviner)所指出的,此答案已被弃用。使用驱动程序,它附带了OOTB承诺。


如果您选择将bluebirds用作承诺库,则可以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驱动程序已经有了承诺(如果您想使用bluebird,则可以在选项中指定,或者因为我确实将其附加到global.Promise),请不要这样做!
John Culviner

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-promisePromise或通过Promisemongodb实用程序包(例如bluebird.promisify


MongoDB驱动程序已经有了承诺(如果您想使用bluebird,则可以在选项中指定,或者因为我确实将其附加到global.Promise),请不要这样做!
John Culviner

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。

然后,定义使用以下承诺的函数:myPromise.then(...)

例如:

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

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

    });
}

这是完整的代码:

http://jsfiddle.net/t5hdjejg/


MongoDB驱动程序已经有了承诺(如果您想使用bluebird,则可以在选项中指定,或者因为我确实将其附加到global.Promise),请不要这样做!
John Culviner

据我所知,@ JohnCulviner .find是否不返回承诺?某些方法可以执行-例如,在游标上执行.count()即可,但是db.mycoll.find({})。then是否未定义?
sil

@sil db.get(“ collection”)。find({something:“ a”})。then()。catch(); 为我工作
Rafique Mohammed '18

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,则可以始终使用ES6 promise polyfill:

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>);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.