Wie verwende ich MongoDB mit Versprechungen in Node.js?


82

Ich habe versucht herauszufinden, wie MongoDB mit Node.js verwendet wird, und in den Dokumenten scheint es die empfohlene Methode zu sein, Rückrufe zu verwenden. Jetzt weiß ich, dass es nur eine Frage der Präferenz ist, aber ich bevorzuge es wirklich, Versprechen zu verwenden.

Das Problem ist, dass ich nicht gefunden habe, wie ich sie mit MongoDB verwenden soll. In der Tat habe ich Folgendes versucht:

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

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

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

Und das Ergebnis ist undefined. In diesem Fall scheint dies nicht der richtige Weg zu sein.

Gibt es eine Möglichkeit, mongo db in Node mit Versprechungen anstelle von Rückrufen zu verwenden?


Antworten:


118

Ihr Ansatz ist fast richtig, nur ein kleiner Fehler in Ihrer Argumentation

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
Genau! MongoDB Node.js Treiber 2.x "Rückgabe: Versprechen, wenn kein Rückruf übergeben wurde" ia vorbei MongoClient.connect. Wenn Sie node.js <4 ohne integrierte ES6-Versprechen haben, können Sie auch ein ES6-kompatibles Versprechen-Shim verwenden oder eine ES6-kompatible Versprechen-Implementierung mit der promiseLibraryOption von bereitstellen MongoClient.connect.
VolkerM

5
Basierend auf einigen Tests erhalten Sie, wenn Sie eine Verbindung zur URL herstellen mongodb//localhost:27017(ohne Angabe einer Datenbank), einen Mongoklienten zurück, sodass Sie anrufen müssen mongoclient.db('example'). Siehe mongodb.github.io/node-mongodb-native/api-generated/…
PatS

22

Sie können auch asynchronisieren / warten

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
}


Ich könnte jetzt dein Gesicht küssen. Dies war die einfachste und beste Antwort, die ich seit Stunden gefunden habe.
Rob E.

Dies ist nur die einfachste, frischeste, vollständigste und aktuellste Antwort. Ich danke dir sehr.
Keuluu

19

Da in keiner der obigen Antworten erwähnt wird, wie dies ohne Bluebird oder Q oder eine andere schicke Bibliothek gemacht werden kann, möchte ich meine 2 Cent dazu addieren.

So erstellen Sie eine Einfügung mit nativen ES6-Versprechungen

    '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;

Ich habe meine open () -Methode als die definiert, die ein Versprechen zurückgibt. Um eine Einfügung durchzuführen, ist hier mein Code-Snippet unten

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});

Hoffentlich hilft das. Wenn Sie Vorschläge haben, um dies zu verbessern, lassen Sie es mich wissen, da ich bereit bin, mich zu verbessern :)


13
Sie wickeln ein Versprechen in ein anderes Versprechen ein. MongoClient-Methoden geben bereits ein Versprechen zurück, und es besteht keine Notwendigkeit, dieses erneut zu verpacken. Dies ist ein typisches Versprechen gegen Muster.
Westor

4
Monate später, aber die Antwort von @ Green 20 Minuten nach dem ursprünglichen Beitrag verwendet mongodb.MongoClients native Versprechensunterstützung und keine fremden Versprechensbibliotheken.
Owen

2
Dies sollte die richtige Antwort sein, da keine Versprechungsbibliotheken von Drittanbietern erforderlich sind.
GlGuru

@westor Wie können Sie ein Versprechen von der open () -Methode zurückgeben, ohne es in ein neues Versprechen einzupacken? Ich denke, das ist der einzige Weg.
Abhishek Nalin

1
Die @ AbhishekNalin MongoDB-Verbindungsmethode (zumindest in neueren Versionen) gibt ein Versprechen zurück. Daher könnten Sie einfach 'mongoClient.connect (url) .then (...)' schreiben oder bei dieser offenen Methode mongoClient.connect (url) zurückgeben. Sie können den Rückruf loswerden. Der Fehlerfall wird hier vom letzten Fang erfasst.
Westor

11

Dies ist eine allgemeine Antwort für Wie verwende ich MongoDB mit Versprechungen in Node.js?

mongodb gibt ein Versprechen zurück, wenn der Rückrufparameter weggelassen wird

Vor der Konvertierung in 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)
        });
    }
})

Nach der Konvertierung in 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) {})

Falls Sie mehrere Anfragen bearbeiten müssen

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
Warum erstellen Sie eine verschachtelte Versprechungskette für den Betrieb nach der Verbindung? Warum nicht:MongoClient.connect(uri).then(client => client.db("db").collection("users").find()).then(data => console.log(data)).catch(err => console.log(err));
SerG

Dies wäre besser mit Links zur Dokumentation
Mikemaccana

Kürzere Notation für catch: .catch (console.log)
Benjam

2

WARNUNG Bearbeiten:

Wie John Culviner feststellte, ist diese Antwort veraltet. Verwenden Sie den Treiber, es kommt mit Versprechen OOTB.


Wenn Sie Bluebird als Versprechensbibliothek verwenden, können Sie die Bluebirds- promisifyAll()Funktion auf MongoClient verwenden:

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
Der MongoDB-Treiber hat bereits Versprechen (wenn Sie Bluebird möchten, können Sie dies in den Optionen angeben oder wie ich es an global.Promise anhänge). TUN SIE DAS NICHT!
John Culviner

2

Ich weiß, dass ich etwas spät zur Party komme, aber ich möchte ein Beispiel mit ES6 teilen

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 };

Ich gehe hier etwas näher darauf ein, wenn Sie einen Blick darauf werfen möchten:

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


Sehr schön. Ich würde nur die Funktion getDbConnection umbenennen, da sie die Verbindung nicht zurückgibt. Es gibt die _db zurück. :)
Kroiz

1

Sie können entweder ein alternatives Paket verwenden, z. B. mongodb-promisedie mongodbPaket-API manuell versprechen oder versprechen, indem Sie Ihre eigenen Versprechungen darauf aufbauen, oder über ein Versprechensdienstprogramm wiebluebird.promisify


Der MongoDB-Treiber hat bereits Versprechen (wenn Sie Bluebird möchten, können Sie dies in den Optionen angeben oder wie ich es an global.Promise anhänge). TUN SIE DAS NICHT!
John Culviner

1

Arbeitslösung mit MongoDB Version> 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

Sie müssen ein Versprechen erstellen, das eine Verbindung zu Mongo herstellt.

Definieren Sie dann Ihre Funktion, die dieses Versprechen verwendet : myPromise.then(...).

Zum Beispiel:

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

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

    });
}

Hier ist der vollständige Code:

http://jsfiddle.net/t5hdjejg/


Der MongoDB-Treiber hat bereits Versprechen (wenn Sie Bluebird möchten, können Sie dies in den Optionen angeben oder wie ich es an global.Promise anhänge). TUN SIE DAS NICHT!
John Culviner

@ JohnCulviner soweit ich das beurteilen kann, gibt .find kein versprechen zurück? Einige Methoden tun dies - zum Beispiel .count () für einen Cursor - aber db.mycoll.find ({}). Ist dann undefiniert?
Sil

@sil db.get ("Sammlung"). find ({etwas: "a"}). then (). catch (); arbeitet für mich
Rafique Mohammed

0

Hier ist ein Einzeiler zum Öffnen der Verbindung

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

und nenne es so

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

-1

Es sieht nicht so aus, als ob für die Verbindungsmethode eine Versprechen-Schnittstelle definiert ist

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

Sie können es jederzeit selbst in der Mongodb-Connector-Bibliothek implementieren, aber das ist wahrscheinlich aufwändiger als Sie suchen.

Wenn Sie wirklich mit Versprechungen arbeiten müssen, können Sie immer die ES6-Versprechens-Polyfüllung verwenden:

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

und wickeln Sie Ihren Verbindungscode damit ein. Etwas wie

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>);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.