Node.js에서 프라 미스와 함께 MongoDB를 사용하는 방법은 무엇입니까?


82

Node.js와 함께 MongoDB를 사용하는 방법을 찾으려고 노력해 왔으며 문서에서 제안 된 방법은 콜백을 사용하는 것 같습니다. 자, 나는 그것이 단지 선호도의 문제라는 것을 알고 있지만, 나는 정말로 promise를 사용하는 것을 선호합니다.

문제는 MongoDB와 함께 사용하는 방법을 찾지 못했다는 것입니다. 실제로 다음을 시도했습니다.

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

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

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

결과는 undefined입니다. 이 경우에는 이것이 방법이 아닌 것 같습니다.

콜백 대신 프라 미스와 함께 Node 내부에서 mongo db를 사용하는 방법이 있습니까?


guru99.com/node-js-promise-generator-event.html 이 튜토리얼이 잘못 되었나요 ???
Ravi Shanker Reddy

답변:


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 by MongoClient.connect. 당신이 내장 ES6 약속없이 Node.js를 <4를 사용한다면, 당신은 또한 ES6 호환 약속 심을 사용하거나하여 ES6 호환 약속 구현을 제공 할 수 promiseLibrary의 옵션을 MongoClient.connect.
VolkerM

5
몇 가지 테스트에 따르면 mongodb//localhost:27017데이터베이스를 지정하지 않고 URL에 연결 하면 mongoclient가 반환되므로 mongoclient.db('example'). mongodb.github.io/node-mongodb-native/api-generated/…
PatS

22

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
}


지금 당신 얼굴에 키스 할 수 있어요. 이것은 내가 몇 시간 만에 찾은 가장 간단하고 최고의 대답이었습니다.
Rob E.

이것은 가장 간단하고 신선하며 가장 완전하고 최신의 가능한 답변입니다. 정말 고맙습니다.
클루

19

위의 답변 중 블루 버드 나 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 메서드는 이미 promise를 반환하고 있으며이를 다시 래핑 할 필요가 없습니다. 이것은 전형적인 약속 안티 패턴입니다.
westor

4
몇 달 후 나올 예정이지만 원본 게시물 20 분 후 @Green의 답변은 mongodb.MongoClient의 기본 약속 지원을 사용하고 외부 약속 라이브러리는 사용하지 않습니다.
오웬

2
타사 promise 라이브러리에 의존하지 않기 때문에 정답이어야합니다.
GlGuru 2018

@westor 새 Promise로 마무리하지 않고 open () 메서드에서 약속을 어떻게 반환합니까? 이것이 유일한 방법이라고 생각합니다.
Abhishek Nalin

1
@AbhishekNalin MongoDB 연결 메서드 (적어도 최신 버전에서는)가 promise를 반환합니다. 따라서 간단하게 'mongoClient.connect (url) .then (...)'을 작성하거나이 open 메서드에서 mongoClient.connect (url)을 반환 할 수 있습니다. 콜백을 제거 할 수 있습니다. 오류 케이스는 여기에서 마지막 캐치로 잡 힙니다.
westor

11

이것은 Node.js에서 Promise와 함께 MongoDB를 사용하는 방법에 대한 일반적인 대답입니다 .

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
연결 후 작업을 위해 중첩 된 약속 체인을 만드는 이유는 무엇입니까? 이유 :MongoClient.connect(uri).then(client => client.db("db").collection("users").find()).then(data => console.log(data)).catch(err => console.log(err));
SerG

이 문서에 대한 링크와 함께 더 나은 것
mikemaccana

catch에 대한 짧은 표기 : .catch (console.log)
Benjam

2

경고 편집 :

John Culviner가 지적했듯이이 답변은 더 이상 사용되지 않습니다. 드라이버를 사용하면 OOTB 약속이 함께 제공됩니다.


bluebird를 promise 라이브러리로 사용하기로 선택한 경우 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 드라이버에는 이미 약속이 있습니다 (블루 버드를 원한다면 옵션에서 지정하거나 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-promise하거나 mongodb주변에 자신의 약속을 구축하거나 다음과 같은 약속 유틸리티 패키지를 통해 패키지 API를 수동으로 약속 할 수 있습니다.bluebird.promisify


MongoDB 드라이버에는 이미 약속이 있습니다 (블루 버드를 원한다면 옵션에서 지정하거나 global.Promise에 첨부 할 수 있습니다)이 작업을 수행하지 마십시오!
John Culviner 2017-06-22

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와 연결되는 약속을 만들어야합니다.

그런 다음이 약속을 사용하는 함수를 정의합니다 myPromise.then(...)..

예를 들면 :

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

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

    });
}

다음은 전체 코드입니다.

http://jsfiddle.net/t5hdjejg/


MongoDB 드라이버에는 이미 약속이 있습니다 (블루 버드를 원한다면 옵션에서 지정하거나 global.Promise에 첨부 할 수 있습니다)이 작업을 수행하지 마십시오!
John Culviner 2017-06-22

@JohnCulviner 내가 말할 수있는 한 .find는 약속을 반환하지 않습니까? 일부 메소드는 예를 들어 커서에서 .count ()를 수행하지만 db.mycoll.find ({}). n은 정의되지 않습니까?
sil

@sil db.get ( "collection"). find ({something : "a"}). then (). catch (); 나를 위해 작동
Rafique 모하메드

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>);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.