Jak używać MongoDB z obietnicami w Node.js?

83

Próbowałem odkryć, jak używać MongoDB z Node.js, aw dokumentacji wydaje się, że sugerowanym sposobem jest użycie wywołań zwrotnych. Teraz wiem, że to tylko kwestia preferencji, ale naprawdę wolę korzystać z obietnic.

Problem w tym, że nie znalazłem sposobu ich użycia w MongoDB. Rzeczywiście, próbowałem następujących rzeczy:

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

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

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

Wynik jest taki undefined. W takim przypadku wydaje się, że nie jest to właściwy sposób.

Czy jest jakiś sposób na użycie mongo db wewnątrz węzła z obietnicami zamiast wywołań zwrotnych?

user1620696
źródło
guru99.com/node-js-promise-generator-event.html Czy ten samouczek jest błędny ???
Ravi Shanker Reddy

Odpowiedzi:

119

Twoje podejście jest prawie poprawne, tylko drobny błąd w twojej argumentacji

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) {})
Zielony
źródło
11
Dokładnie! MongoDB node.js kierowcy 2.x „Powroty: Obietnica jeśli nie zwrotna przekazywana” między innymi przez MongoClient.connect. Jeśli masz node.js <4 bez wbudowanych obietnic ES6, możesz również użyć podkładki obietnicy zgodnej z ES6 lub zapewnić implementację obietnicy zgodną z ES6 za pomocą promiseLibraryopcji MongoClient.connect.
VolkerM
5
Na podstawie niektórych testów, jeśli łączysz się z adresem URL mongodb//localhost:27017(bez określania bazy danych), otrzymujesz mongoklienta, więc musisz zadzwonić mongoclient.db('example'). Zobacz mongodb.github.io/node-mongodb-native/api-generated/…
PatS
23

Możesz także wykonać 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
}

ginad
źródło
Mógłbym teraz pocałować twoją twarz. To była najprostsza, najlepsza odpowiedź, jaką znalazłem w ciągu kilku godzin.
Rob E.
To tylko najprostsza, najświeższa, najbardziej kompletna i aktualna odpowiedź. Dziękuję bardzo.
keuluu
19

Ponieważ żadna z powyższych odpowiedzi nie wspomina, jak to zrobić bez bluebirda, q lub innej wymyślnej biblioteki, pozwól, że dodam do tego moje 2 centy.

Oto, jak wykonać wkładkę z natywnymi obietnicami 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;

Zdefiniowałem moją metodę open () jako zwracającą obietnicę. Aby wykonać wstawianie, poniżej znajduje się mój fragment kodu

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

Mam nadzieję, że to pomoże. Jeśli masz jakieś sugestie, jak to ulepszyć, daj mi znać, ponieważ jestem gotów się poprawić :)

PirateApp
źródło
13
Zawijasz obietnicę w inną obietnicę. Metody MongoClient już zwracają obietnicę i nie ma potrzeby jej ponownego zawijania. Jest to typowy anty-wzór obietnicy.
westor
4
Pojawi się kilka miesięcy później, ale odpowiedź @ Greena 20 minut po oryginalnym poście używa natywnego wsparcia obietnicy mongodb.MongoClient i żadnych obcych bibliotek obietnic.
Owen
2
Powinna to być poprawna odpowiedź, ponieważ nie polega na żadnych bibliotekach obietnic stron trzecich.
GlGuru
@westor w jaki sposób zwrócisz obietnicę z metody open () bez pakowania jej w nową obietnicę? Myślę, że to jedyny sposób.
Abhishek Nalin
1
@AbhishekNalin Metoda łączenia MongoDB (przynajmniej w nowszych wersjach) zwraca obietnicę. Dlatego po prostu możesz napisać „mongoClient.connect (url) .then (...)” lub w tej otwartej metodzie zwróć mongoClient.connect (url). Możesz pozbyć się oddzwonienia. Przypadek błędu jest wychwytywany przez ostatni haczyk tutaj.
zachód lub
11

To jest ogólna odpowiedź na temat Jak używać MongoDB z obietnicami w Node.js?

mongodb zwróci obietnicę, jeśli parametr callback zostanie pominięty

Przed przejściem na 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)
        });
    }
})

Po przejściu na 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) {})

W przypadku, gdy musisz obsłużyć wiele żądań

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
źródło
1
Dlaczego tworzysz zagnieżdżony łańcuch obietnic do działania po połączeniu? Dlaczego nie:MongoClient.connect(uri).then(client => client.db("db").collection("users").find()).then(data => console.log(data)).catch(err => console.log(err));
SerG
Byłoby lepiej z linkami do dokumentacji
mikemaccana
Krótszy zapis dla połowu: .catch (console.log)
Benjam
2

OSTRZEŻENIE Edytuj:

Jak zauważył John Culviner, ta odpowiedź jest przestarzała. Użyj sterownika, jest wyposażony w obietnice OOTB.


Jeśli zdecydujesz się używać bluebird jako biblioteki obietnic, możesz użyć promisifyAll()funkcji bluebirds w 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);
});
Simon Z.
źródło
6
Sterownik MongoDB ma już obietnice (jeśli chcesz bluebirda, możesz określić go w opcjach lub tak jak ja dołączam go do global. Obietnica) NIE ROBIĆ TEGO!
John Culviner
2

Wiem, że trochę się spóźniłem na imprezę, ale chciałbym podzielić się przykładem z użyciem 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 };

Podaję nieco więcej szczegółów, jeśli chcesz się przyjrzeć:

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

Alex Garcia
źródło
bardzo dobrze. Po prostu zmieniłbym nazwę funkcji getDbConnection, ponieważ nie zwraca ona połączenia. Zwraca _db. :)
kroiz
1

Możesz użyć alternatywnego pakietu, takiego jak mongodb-promiselub obiecać mongodbinterfejs API pakietu ręcznie, budując wokół niego własne obietnice lub za pośrednictwem pakietu narzędzi promise, takiego jakbluebird.promisify

markusthoemmes
źródło
Sterownik MongoDB ma już obietnice (jeśli chcesz bluebirda, możesz określić go w opcjach lub tak jak ja dołączam go do global. Obietnica) NIE ROBIĆ TEGO!
John Culviner
1

Działające rozwiązanie z MongoDB w wersji> 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
źródło
0

Musisz stworzyć obietnicę, która łączy się z Mongo.

Następnie zdefiniować funkcję, która korzysta z tej obietnicy: myPromise.then(...).

Na przykład:

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

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

    });
}

tutaj jest pełny kod:

http://jsfiddle.net/t5hdjejg/

Maria Maldini
źródło
Sterownik MongoDB ma już obietnice (jeśli chcesz bluebirda, możesz określić go w opcjach lub tak jak ja dołączam go do global. Obietnica) NIE ROBIĆ TEGO!
John Culviner
@JohnCulviner, o ile wiem, .find nie zwraca obietnicy? Niektóre metody robią - na przykład .count () na kursorze - ale db.mycoll.find ({}). Wtedy jest niezdefiniowane?
sil
@sil db.get ("kolekcja"). znajdź ({coś: "a"}). then (). catch (); pracuje dla mnie
Rafique Mohammed
0

Oto jedna linijka do otwarcia połączenia

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

i nazwij to tak

const login = async () => 
const client = await openConnection()
nacięcie
źródło
-1

Wygląda na to, że metoda connect nie ma zdefiniowanego interfejsu obietnicy

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

zawsze możesz zaimplementować to samodzielnie w bibliotece łączników Mongodb, ale jest to prawdopodobnie bardziej skomplikowane niż szukasz.

Jeśli naprawdę potrzebujesz pracować z obietnicami, zawsze możesz użyć wypełnienia obietnicy ES6:

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

i opakuj w to swój kod połączenia. Coś jak

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
źródło