91

I'm trying to develop a class on the top of the mongoose with my custom methods, so I extended the mongoose with my own class but when I invoke to create a new car method it works but its strip and error, here I let you see what I'm trying to do.

I'm getting this warning

(node:3341) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

after I do

driver.createCar({
      carName: 'jeep',
      availableSeats: 4,
    }, callback);

driver is an instance of Driver class

const carSchema = new Schema({
  carName: String,
  availableSeats: Number,
  createdOn: { type: Date, default: Date.now },
});
const driverSchema = new Schema({
 email: String,
 name: String,
 city: String,
 phoneNumber: String,
 cars: [carSchema],
 userId: {
   type: Schema.Types.ObjectId,
   required: true,
 },
createdOn: { type: Date, default: Date.now },
});
const DriverModel = mongoose.model('Driver', driverSchema);

class Driver extends DriverModel {
  getCurrentDate() {
  return moment().format();
}
create(cb) {
  // save driver
  this.createdOn = this.getCurrentDate();
  this.save(cb);
}
remove(cb) {
  super.remove({
  _id: this._id,
 }, cb);
}
createCar(carData, cb) {
  this.cars.push(carData);
  this.save(cb);
}
getCars() {
  return this.cars;
 }
}

any thoughts about what Im doing wrong?

rahul singh Chauhan
  • 323
  • 1
  • 4
  • 15
Audel O. Gutierrez
  • 1,031
  • 1
  • 8
  • 7
  • 3
    The writer of Mongoose says that: "Just do `mongoose.Promise = global.Promise` and you shouldn't get that warning anymore." https://github.com/Automattic/mongoose/issues/4291#issuecomment-230312093 – efkan Jan 25 '17 at 07:40

8 Answers8

241

Here's what worked for me to clear up the issue, after reading docs: http://mongoosejs.com/docs/promises.html

The example in the doc is using the bluebird promise library but I chose to go with native ES6 promises.

In the file where I'm calling mongoose.connect:

mongoose.Promise = global.Promise;
mongoose.connect('mongodb://10.7.0.3:27107/data/db');

[EDIT: Thanks to @SylonZero for bringing up a performance flaw in my answer. Since this answer is so greatly viewed, I feel a sense of duty to make this edit and to encourage the use of bluebird instead of native promises. Please read the answer below this one for more educated and experienced details. ]

Hunter Lester
  • 2,972
  • 3
  • 15
  • 19
  • 3
    After verifying the benchmark on the website: http://bluebirdjs.com/docs/benchmarks.html @SylonZero is referring to, I do believe his solution in worth to up vote instead of the first proposal. I still thank Hunter Lester for this great work and investigation and sharing his findings! – Isak La Fleur Feb 02 '17 at 07:07
  • Thanks for your edit which makes me realize a huge performance flaw – Yusuf Kamil AK Dec 21 '17 at 16:15
73

While the answer above is accurate and works, you have to account for the issue of Performance if you have a real, production Node app.

The solution above will use native ES6 promises - which are 4X slower than bluebird in the benchmarks I've shared below. This could dramatically affect the performance of an API written in Node and using MongoDB.

I recommend using Bluebird:

// Assuming you store the library in a var called mongoose
var mongoose = require('mongoose');

// Just add bluebird to your package.json, and then the following line should work
mongoose.Promise = require('bluebird');

Benchmark Results

Platform: (using latest Node at time of writing)

  • Linux 4.4.0-59-generic x64
  • Node.JS 6.9.4
  • V8 5.1.281.89
  • Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz × 4
  • 16 GB RAM with 500 GB SSD

    | file                                      | time(ms) | memory(MB) |
    |-------------------------------------------|----------|------------|
    | callbacks-baseline.js                     | 114      | 25.09      |
    | callbacks-suguru03-neo-async-waterfall.js | 152      | 32.98      |
    | promises-bluebird-generator.js            | 208      | 29.89      |
    | promises-bluebird.js                      | 223      | 45.47      |
    | promises-cujojs-when.js                   | 320      | 58.11      |
    | promises-then-promise.js                  | 327      | 64.51      |
    | promises-tildeio-rsvp.js                  | 387      | 85.17      |
    | promises-lvivski-davy.js                  | 396      | 81.18      |
    | callbacks-caolan-async-waterfall.js       | 527      | 97.45      |
    | promises-dfilatov-vow.js                  | 593      | 148.30     |
    | promises-calvinmetcalf-lie.js             | 666      | 122.78     |
    | generators-tj-co.js                       | 885      | 121.71     |
    | promises-obvious-kew.js                   | 920      | 216.08     |
    | promises-ecmascript6-native.js            | 931      | 184.90     |
    | promises-medikoo-deferred.js              | 1412     | 158.38     |
    | streamline-generators.js                  | 1695     | 175.84     |
    | observables-Reactive-Extensions-RxJS.js   | 1739     | 218.96     |
    | streamline-callbacks.js                   | 2668     | 248.61     |
    | promises-kriskowal-q.js                   | 9889     | 410.96     |
    | observables-baconjs-bacon.js.js           | 21636    | 799.09     |
    | observables-pozadi-kefir.js               | 51601    | 151.29     |
    | observables-caolan-highland.js            | 134113   | 387.07     |
Ray
  • 3,864
  • 7
  • 24
  • 36
SylonZero
  • 1,207
  • 8
  • 9
  • 1
    for my understanding: where is your benchmark coming from? Is there a consensus around these results? It seems like everybody is voting for the default ES6 promise answer but I would like to dig deeper in the performance issues you mention. – Zedenem Feb 01 '17 at 16:31
  • 1
    The benchmark is from a suite of tests that you can read (and vet) from the bluebird git repo - I ran them again locally to get the results above because I needed 2017 results to share with others. More importantly, I've experienced performance gains in our own API (I have 5 micro services and a tough scalability target) and have had to often make decisions to use simple nested callbacks over promises (still the fastest). I personally think benchmarks are only a first step towards a decision but I cannot share my internal data just yet...my scale target is 10K Users per physical machine. – SylonZero Feb 01 '17 at 17:32
  • Also, the upvoting is hardly a full measure about an answer. In my experience, many rarely dig deep after a problem has been solved (or read anything else) and many programmers I've mentored in the past needed to be taught about performance and instrumentation skills for code. – SylonZero Feb 01 '17 at 17:36
  • 1
    Thank you so much for bringing up the performance issues. I'm a novice programmer, only 2 years at it, and crave this education. I am using this in production, so I'm even more so glad to know if it. What are the best ways to go about benchmarking programs and pieces of code? – Hunter Lester Feb 02 '17 at 07:19
  • 1
    Hunter, that would depend on the nature of the platform and the code but related to this question: there are two sides to getting insight - 1. good tests to use via a load generator to simulate user requests. I use Apache jMeter to test my Node API and to generate load for multiple users. 2. Instrumentation: how do you track the individual transactions. I use NewRelic to instrument my Node code - it gives a detailed breakdown of every transaction in ms (down to the Express route, Mongo query time, Redis for sessions etc). Hope this gets you started. – SylonZero Feb 02 '17 at 13:31
  • If using this I get `ECONNREFUSED` throwed from mongo. Without that line it is connecting... – C4d Jun 19 '17 at 09:39
  • @C4u not sure how a deprecation warning would have anything to do with a connection being refused. Unless they have made the driver stricter and are now refusing to connect without promises set up (seems unlikely). If for some reason that is the case, then you need to ensure you are setting up the promise reference at the right *time* prior to connecting...I can't think of any other reason why this would go wrong. I use this in production right now and there are no issues. – SylonZero Jun 21 '17 at 03:47
  • @SylonZero Thanks for that comment. The problem was a bit strange: I had a problem with the mongodb installation that wasn't showing up. Only when using `promise` the error was raising. Falsely I then thought there would be a dependence. So everything is cool. This one is working for me :). Upped it. – C4d Jun 21 '17 at 08:15
2

did you try this? For Example :

const mongoose = require('mongoose')
mongoose.Promise = global.Promise // <--
const Schema = mongoose.Schema
const UserSchema = new Schema({
  name: String,
})
const User = mongoose.model('user', UserSchema)
module.exports = User

if you create a model from a mongoose instance who's promise wasn't redefined - every query on this model would throw the warning.

2

I think you have your answer but I use global.promise with error handling

// MongoDB connection
mongoose.Promise = global.Promise;

var promise = mongoose.connect('mongodb://localhost:27017/test_db', {
  useMongoClient: true,
});

promise.then(function(db) {
    console.log("Connected to database!!!");
}, function(err){
    console.log("Error in connecting database " + err);
});
Saurabh Lende
  • 953
  • 2
  • 13
  • 19
1
var mydb;
var uri = 'mongodb://localhost/user1';
var promise = mongooose.connect(uri,{
      useMongoClient: true,
});
promise.openUri(uri,function(errr,db){
if(errr){
        throw errr;
      }else{
        console.log("Connection Successfull");      
        mydb = db;
      }
});

One needs to have connection with the help of promise in the latest version of mongoose [this is the link][1] [1]: http://mongoosejs.com/docs/promises.html

0

Just add the second parameter as an object to the connect() method.

mongoose.connect('dbUrl', {
  useMongoClient: true
});

See: http://mongoosejs.com/docs/connections.html#use-mongo-client

Aaman
  • 19
  • 5
0

Mongoose 4.8.6

If you catch error like this:

(node:9600) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

You need also to set in options which promise library to use for the driver.

mongoose.Promise = global.Promise
mongoose.connect(uri, { useMongoClient: true, options: { promiseLibrary: mongoose.Promise }})
Community
  • 1
  • 1
dimpiax
  • 12,093
  • 5
  • 62
  • 45
0
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
db = mongoose.connect(env.DATABASE_URI, function(){
  //
})

this work for me.

Sigit
  • 728
  • 7
  • 12