Mongoose: DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

Created on 18 Aug 2018  ·  32Comments  ·  Source: Automattic/mongoose

After update to version 5.2.9 I'm getting this message in console all the time, when I start my web app:

DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

And I don't use neither of them.

enhancement

Most helpful comment

After upgrading to version 5.2.10. Any of the options below should stop the warnings?

js mongoose.connect(config.dbUri, { useCreateIndex: true, useNewUrlParser: true })
or
js mongoose.set('useCreateIndex', true) mongoose.connect(config.dbUri, { useNewUrlParser: true })
It didnt work here. (Sorry if I did something wrong)

All 32 comments

duplicate of #6880

Thanks for taking the time to report the issue @bricss. Mongoose calls ensureIndex() internally. You can safely ignore the warning for now, or silence it with the node flag --no-deprecation, or downgrade to 5.2.8 if there are no specific fixes in 5.2.9 that you were relying on. Follow #6880 for updates 👍

,unique: true,index: true is on one field in one of my schemas and it triggers this warning. Question how to ensure a unique value without getting this warning.

@nonniv upgrade to 5.2.10 and set mongoose.set('useCreateIndex', true);

After upgrading to version 5.2.10. Any of the options below should stop the warnings?

js mongoose.connect(config.dbUri, { useCreateIndex: true, useNewUrlParser: true })
or
js mongoose.set('useCreateIndex', true) mongoose.connect(config.dbUri, { useNewUrlParser: true })
It didnt work here. (Sorry if I did something wrong)

@samuelcecilio what specific deprecation warnings are you seeing? There are some helpful notes in the comment that opened #6922, or feel free to share your specific warnings here and I'll see if I can help.

(node:9125) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

@samuelcecilio the mongoose.set('useCreateIndex', true) should stop that warning as demonstrated by this example:

6922.js

#!/usr/bin/env node
'use strict';

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
mongoose.set('useCreateIndex', true);

const conn = mongoose.connection;
const Schema = mongoose.Schema;

const schema = new Schema({
  name: {
    type: String,
    unique: true
  }
});

const Test = mongoose.model('test', schema);

const test = new Test({ name: 'one' });

async function run() {
  console.log(`mongoose version: ${mongoose.version}`);
  await conn.dropDatabase();
  await test.save();
  return conn.close();
}

run();

Output:

issues: ./6922.js
mongoose version: 5.2.10
issues:

are you certain that your project is using 5.2.10? are there other packages in your project using other versions of mongoose, etc?

Hi, thanks for the reply. Yes, I checked the version three times lol:

$ npm list --depth=0 ... [email protected] ...

My code

app.js
````js
...

const config = require('./config')
const mongoose = require('mongoose')
const express = require('express')
const app = express()

mongoose.connect(config.dbUri, { useNewUrlParser: true })
mongoose.set('useCreateIndex', true)

....

module.exports = app
````

bin/www
````js

!/usr/bin/env node

const app = require('../app')
const config = require('../config')
const debug = require('debug')('blitz')
const http = require('http')
const port = normalizePort(process.env.PORT || config.port)
const mongoose = require('mongoose')

app.set('port', port)

const server = http.createServer(app)

server.listen(port)
server.on('error', onError)
server.on('listening', onListening)

const mongo = mongoose.connection

mongo.on('error', error => { debug('mongo: ' + error.name) })
mongo.on('connected', () => { debug('mongo: Connected') })
mongo.on('disconnected', () => { debug('mongo: Disconnected') })

....
````

When I run DEBUG=blitz* npm run dev

````bash

nodemon bin/www

[nodemon] 1.18.3
[nodemon] to restart at any time, enter rs
[nodemon] watching: .
[nodemon] starting node bin/www
blitz Listening on port 3000 +0ms
blitz mongo: Connected +14ms
(node:10622) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
````

@samuelcecilio maybe move the mongoose.set('useCreateIndex', true) to the bin/www file instead? I'll setup an express example and test as well.

@samuelcecilio after playing around with this some, I found that I needed to set useCreateIndex to true in the route file that contained the model. In my case, after using the express cli tool, I needed to set useCreateIndex in the index route shown below:

var express = require('express');
var router = express.Router();
const mongoose = require('mongoose');
mongoose.set('useCreateIndex', true);
const Test = mongoose.model('test', { name: {type: String, unique: true }});

/* GET home page. */
router.get('/', function(req, res, next) {
  Test.create({ name: 'billy' }).then((doc) => {
    return res.status(200).json({ done: true, test: doc.id });
  }).catch((e) => {
    return res.status(500).json({ err: e });
  });
});

module.exports = router;

without the option set in the index route I got:

[nodemon] starting `node bin/www`
version: 5.2.10
(node:17042) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

after setting the option in the route I got:

[nodemon] starting `node bin/www`
version: 5.2.10
^C

I tried setting it in bin/www but that did not get rid of the warning. Only setting it in the route was successful.

output of curling localhost

~>: curl localhost:3000/
{"done":true,"test":"5b84a4e13ec72e4352475426"}~>: 
~>: 

I use separate files for users, customers, suppliers, orders, items..

This stopped the warning:

models/user.js
````js
const addressSchema = require('./address')
const profileSchema = require('./profile')
const uuidv4 = require('uuid/v4')
const mongoose = require('mongoose')
const Schema = mongoose.Schema

mongoose.set('useCreateIndex', true)

const userSchema = new Schema({
disabled: { type: Boolean, default: false },
roles: { type: Array, default: [ 'assistant' ] },
identity: { type: String, unique: true, required: true },
username: { type: String, unique: true, required: true },
name: { type: String, uppercase: true, required: true },
password: { type: String, required: true },
secret: String,
profile: profileSchema,
address: addressSchema,
created: Date,
modified: Date
}, {
collection: 'users'
})

userSchema.pre('save', function (next) {
const doc = this
doc.created = Date.now()
doc.modified = Date.now()
doc.secret = uuidv4()
next()
})

module.exports = mongoose.model('User', userSchema)

````

I figured it would be some global setting, but apparently I have to add in all the files.

@samuelcecilio you could wrap mongoose in a custom file, something like

myMongoose.js

const mongoose = require('mongoose')
mongoose.set('useCreateIndex', true);
//etc
module.exports = mongoose

and then require your wrapper const mongoose = require('myMongoose') instead of mongoose everywhere. That's probably something like what I'll end up having to do when I start upgrading beyond 5.2.8.

Still I would have to modify all current files. For each file in the models folder, I would replace require ('mongoose') with require('myMongoose'). The same would apply to app.js and bin/www.

The question is: in a future version of mongoose I will not need to include mongoose.set ('useCreateIndex', true) or will this be normal, for compatibility issues with older versions of mongo, node, etc ...?

I suspect the behavior will remain as it is now ( having to set the variable, not the internal implementation of it ) until the next major version (ie 6.0.0 ) of mongoose.

For now, I've added mongoose.set('useCreateIndex', true) to all files that contain require('mongoose'). I'm thinking of using a wrapper ('./myMongoose') or ('./mongoose-custom'). What do you think?

Should this be global? Is it an express issue?

It's really uncomfortable to add mongoose.set('useCreateIndex', true) in every single file that contain model declarations.
Why is not make it work from connect options as well, or set it before connection?

@samuelcecilio @bricss Agreed. Reopening this to investigate potential solutions.

You don't need to put this in every file, but unfortunately it looks like right now you need to put mongoose.set('useCreateIndex', true) before any mongoose.model() calls. That is tricky if you export models as opposed to schemas. Will add a fix for this.

After upgrading to version 5.2.13, should this stop the warnings? Thanks

javascript mongoose.connect(config.dbUri, { useCreateIndex: true, useNewUrlParser: true })

bash the options [useCreateIndex] is not supported server: listening on port 3000 +0ms mongo: Connected +34ms (node:18457) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

@samuelcecilio useCreateIndex isn't a connection option, but as long as you call mongoose.set('useCreateIndex', true); before calling mongoose.model() ( even in other files ) all subsequent calls to mongoose.model should fallback to the option you set with mongoose.set(). I tested 5.2.13 with my example above, instead calling mongoose.set('useCreateIndex', true) in the bin/www file and not in my route. It works now.

It works with 5.2.13 after connection and before all other files.

This is connection in my db.js file:

// Create the database connection
mongoose.connect(encodeMongoURI(dbURI), options);
mongoose.set('useCreateIndex', true);

I have my mongo connection in a separate script. This way I just call mongoose.set('useCreateIndex', true); right before actually connecting to mongo. Then there's no need to put it in any of my model declarations.

@LucHighwalker 's suggestion is the right way to do this. Ideally you put all these global options right before your call to mongoose.connect().

Is there any functional difference between

mongoose.connect(encodeMongoURI(dbURI), options);
mongoose.set('useCreateIndex', true);

and

mongoose.set('useCreateIndex', true);
mongoose.connect(encodeMongoURI(dbURI), options);

? Because both seem to work just fine in 5.2.17

mongoose.connect(config.dbUri, { useCreateIndex: true, useNewUrlParser: true })

Works with the latest version

Okay, i guess @types/mongoose is some versions behind then (doesn't work on typescript yet).

mongoose.connect(url, { useNewUrlParser: true, autoIndex: false })

@Dionesio's answer did the trick to me. Thanks!

mongoose.connect("mongodb://localhost:27017/test", {useNewUrlParser: true});
mongoose.set('useCreateIndex', true);

This solved all my deprecation warnings.

@samuelcecilio after playing around with this some, I found that I needed to set useCreateIndex to true in the route file that contained the model. In my case, after using the express cli tool, I needed to set useCreateIndex in the index route shown below:

var express = require('express');
var router = express.Router();
const mongoose = require('mongoose');
mongoose.set('useCreateIndex', true);
const Test = mongoose.model('test', { name: {type: String, unique: true }});

/* GET home page. */
router.get('/', function(req, res, next) {
  Test.create({ name: 'billy' }).then((doc) => {
    return res.status(200).json({ done: true, test: doc.id });
  }).catch((e) => {
    return res.status(500).json({ err: e });
  });
});

module.exports = router;

without the option set in the index route I got:

[nodemon] starting `node bin/www`
version: 5.2.10
(node:17042) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

after setting the option in the route I got:

[nodemon] starting `node bin/www`
version: 5.2.10
^C

I tried setting it in bin/www but that did not get rid of the warning. Only setting it in the route was successful.

output of curling localhost

~>: curl localhost:3000/
{"done":true,"test":"5b84a4e13ec72e4352475426"}~>: 
~>: 

Thanks - Adding mongoose.set('useCreateIndex', true); fixed my issue

I'm going to lock this issue. For future reference, see the deprecations guide on our docs

Was this page helpful?
0 / 5 - 0 ratings