Як використовувати MongoDB з обіцянками в Node.js?


83

Я намагався виявити, як використовувати 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. У такому випадку здається, що це не спосіб це зробити.

Чи є спосіб використовувати mongo db всередині Node з обіцянками замість зворотних викликів?


guru99.com/node-js-promise-generator-event.html Цей підручник помилковий ???
Раві Шенкер Редді

Відповіді:


119

Ваш підхід майже правильний, лише крихітна помилка в аргументації

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 "Повертає: обіцяє, якщо зворотний виклик не передано" , тобто MongoClient.connect. Якщо у вас є node.js <4 без вбудованих обіцянок ES6, ви також можете використовувати сумісний ES6 обіцянку або забезпечити реалізацію обіцянки, сумісної з ES6, за допомогою promiseLibraryопції MongoClient.connect.
VolkerM

5
На підставі деяких тестувань, якщо ви підключаєтеся до URL-адреси mongodb//localhost:27017(без вказівки бази даних), ви отримуєте монгокліент, тому вам потрібно зателефонувати mongoclient.db('example'). Дивіться mongodb.github.io/node-mongodb-native/api-generated/…
PatS

23

Ви також можете виконати асинхронізацію / очікування

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
}


Я міг би поцілувати тобі обличчя прямо зараз. Це була найпростіша, найкраща відповідь, яку я знайшов за години.
Роб Е.

Це просто найпростіша, найсвіжіша та найповніша та найсучасніша відповідь. Дуже дякую.
keuluu

19

Оскільки жоден з наведених вище відповідей не згадує, як це зробити без bluebird чи q чи будь-якої іншої вишуканої бібліотеки, дозвольте мені додати свої 2 центи на це.

Ось як ви робите вставку з власними обіцянками ES6

    '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 вже повертають обіцянку, і немає потреби обгортати це знову. Це типовий перспективний анти-шаблон.
вестор

4
Продовжується місяцями пізніше, але відповідь @ Green через 20 хвилин після вихідної публікації використовує рідну підтримку обіцянок mongodb.MongoClient і відсутність сторонніх бібліотек обіцянок.
Оуен

2
Це має бути правильною відповіддю, оскільки вона не покладається на жодну бібліотеку обіцянок.
GlGuru,

@westor, як ви повернете обіцянку з методу open (), не обертаючи її новим Promise? Я думаю, що це єдиний спосіб.
Абхішек Налін

1
Метод підключення @AbhishekNalin MongoDB (принаймні в новіших версіях) повертає обіцянку. Тому ви просто можете написати "mongoClient.connect (url). Then (...)" або в цьому відкритому методі ви повернете mongoClient.connect (url). Ви можете позбутися зворотного дзвінка. Випадок помилки фіксується останнім уловом тут.
Вестор,

11

Це загальна відповідь щодо Як використовувати MongoDB з обіцянками в Node.js?

mongodb поверне обіцянку, якщо параметр зворотного виклику опущений

Перед переходом на 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
Чому ви створюєте ланцюжок вкладених обіцянок для роботи після підключення? Чому б і ні: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

ПОПЕРЕДЖЕННЯ Редагувати:

Як зазначив Джон Калвінер, ця відповідь застаріла. Використовуйте драйвер, він поставляється з обіцянками OOTB.


Якщо ви вирішите використовувати bluebird як бібліотеку обіцянок, ви можете використовувати promisifyAll()функцію bluebirds на MongoClient:

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), НЕ РОБІТЬ ЦЬОГО!
Джон Калвінер,

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-promiseабо проміффікувати mongodbAPI пакета вручну, побудувавши навколо нього власні обіцянки, або за допомогою пакета утиліт обіцянки, наприкладbluebird.promisify


Драйвер MongoDB вже обіцяє (якщо ви хочете bluebird, ви можете вказати у параметрах або, як я це додаю до global.Promise), НЕ РОБІТЬ ЦЬОГО!
Джон Калвінер,

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

Вам потрібно створити обіцянку, яка пов’язує з Монго.

Потім визначте функцію , яка використовує цю обіцянку: 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), НЕ РОБІТЬ ЦЬОГО!
Джон Калвінер,

@JohnCulviner, наскільки я можу зрозуміти, .find не повертає обіцянку? Деякі методи роблять - .count () на курсорі, наприклад, - але db.mycoll.find ({}). Тоді не визначено?
sil

@sil db.get ("колекція"). find ({щось: "a"}). then (). catch (); працює для мене
Рафік Мохаммед

0

Ось один вкладиш, щоб відкрити з’єднання

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

і називати це так

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

-1

Схоже, метод підключення не має визначеного інтерфейсу обіцянки

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

Ви завжди можете самостійно реалізувати це в бібліотеці сполучників Mongodb, але це, мабуть, більше залучене, ніж ви шукаєте.

Якщо вам дійсно потрібно працювати з обіцянками, ви завжди можете скористатися поліполивною заповненням ES6:

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>);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.