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?

user1620696
quelle
guru99.com/node-js-promise-generator-event.html Ist dieses Tutorial falsch ???
Ravi Shanker Reddy

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) {})
Grün
quelle
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
}

Ginad
quelle
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 :)

PirateApp
quelle
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) {})
Siva Kannan
quelle
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);
});
Simon Z.
quelle
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

Alex Garcia
quelle
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

Markusthoemmes
quelle
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)
    })
Dimitar Zafirov
quelle
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/

Maria Maldini
quelle
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()
Nick
quelle
-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>);
andrewkodesgood
quelle