Mongoose: Deprecated collection methods from mongodb

Created on 17 Aug 2018  ·  28Comments  ·  Source: Automattic/mongoose

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

Model.findByIdAndUpdate() is issuing a deprecation warning for mongodb - which has deprecated collection.findAndModify. Mongodb suggests using findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.

collection.ensureIndex is also deprecated - mongodb suggests using createIndexes instead.

If the current behavior is a bug, please provide the steps to reproduce.

Using Model.findByIdAndUpdate / findOneAndUpdate to alter a document returns these deprecation warnings.

What is the expected behavior?

No deprecation warnings!

Please mention your node.js, mongoose and MongoDB version.

Node v10.8.0
mongodb v3.6.2
mongoose v5.2.9

Most helpful comment

Same here. I also get "find option [fields] is deprecated and will be removed in a later version."

All 28 comments

Same here. I also get "find option [fields] is deprecated and will be removed in a later version."

(node:13076) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
(node:13076) DeprecationWarning: collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead.
(node:13076) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.
(node:13076) DeprecationWarning: collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.

Here's some other ones I got

Related to #6165 and can be reproduced on CI test

You can specify useFindAndModify to false to prevent partial deprecation message. IMO this should be default to false now.

mongoose.set('useFindAndModify', false);

Warning: Do not set this option to false in production without proper testing

However, other deprecated methods like ensureIndex(es) and update still need to be superseded with new API too. Setting this option to false won't fix this.
Maybe we need to update all deprecated method and remove useFindAndModify options in the next major release?

Note:
Only MongoDB 3.2+ support findOneAndUpdate series query but the underlying [email protected] library still use findAndModify polyfill to remain compatibility back to 2.6 so making useFindAndModify default to false won't actually drop support for MongoDB 3.0 currently.

However this compatibility definitely will break soon as they have been marked as deprecated since [email protected] (very long time ago) and now even throw warning messages.

Hence, I suggest next major release of mongoose (6.x) deprecate MongoDB 3.0 support and adopt all new API. Furthermore, MongoDB 3.0 has reached End-of-life in February, 2018, half of a year ago.

Any thoughts?

So ... why is this happening? Is it necessary to wait until the next mongoose major release?

@lpiVasquez it's because the document says mongoose 5.x support MongoDB Server 3.0.

For now it’s safe to just use the new API because underlying API still handling this for us. However it won’t work once the underlying library change this behavior and we need to be very careful when upgrading the underlying library.

What I mean is not ignoring the issue but dropping support for MongoDB Server 3.0 in the next release 5.3. At least don’t break in 5.2. Just my opinion though.

@IpiVasquez

if by,

why is this happening?

you mean,

why is mongodb deprecating these APIs

Mongodb has a plan in place to make the various driver APIs more consistent. This is documented here in the mongodb crud spec

Is it necessary to wait until the next mongoose major release?

If we stick to the semver spec, then anything that breaks the API should happen in a MAJOR release, like @6.0.0 as opposed to a minor release like @5.3.0 or a patch release like @5.2.10.

Looking back at the history of the native driver, I wouldn't expect them to remove these methods until v4 of the driver.

In the meantime, I think most of the deprecation warnings I've seen so far can be mitigated in userland by not calling deprecated methods. I'm guessing most of these methods will be removed in mongoose @6.0.0 anyway.

I think the 2 main issues for us to deal with in mongoose sooner rather than later are substituting projections for fields in query options ( works back to at least server version 3.0.15 ) and potentially changing the default value of useFindAndModify as described by @Fonger, with one addendum:

findOneAndUpdate in the native driver will call findAndModify for you internally ( without the deprecation warning ) when you're connected to a server pre 3.2, so findOneAndUpdate in mongoose still works with mongodb pre 3.2 and useFindAndModify: false as demonstrated in this example:

6880.js

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

const mongoose = require('mongoose');
mongoose.set('useFindAndModify', false);

const url = 'mongodb://localhost:27017/test';
const opts = { useNewUrlParser: true };

mongoose.connect(url, opts);
const conn = mongoose.connection;
const Schema = mongoose.Schema;

const schema = new Schema({
  name: String
});

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

async function run() {
  await conn.dropDatabase();
  let admin = conn.db.admin();
  let { version } = await admin.serverInfo();
  console.log(`mongodb: ${version}`);
  console.log(`mongoose: ${mongoose.version}`);

  let cond = {};
  let update = { name: 'Sarah' };
  let opts = {
    upsert: true,
    new: true
  };

  let sarah = await Test.findOneAndUpdate(cond, update, opts);
  console.log(sarah);
  return conn.close();
}

run();

Output:

issues: ./6880.js
mongodb: 3.0.15
mongoose: 5.2.9
{ _id: 5b779ca8d1326ce227b6869f, __v: 0, name: 'Sarah' }
issues:

You can also demonstrate this with just the native driver like this:

6880_native.js

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

const { MongoClient, Logger } = require('mongodb');

const uri = 'mongodb://localhost:27017/test';
const opts = { 
  useNewUrlParser: true
};

async function run() {
  const client = new MongoClient(uri, opts);
  await client.connect();
  const db = client.db('gh-6881');
  await db.dropDatabase().catch(handleError);

  Logger.setLevel('debug');
  let res = await db
    .collection('tests')
    .findOneAndUpdate({}, { $set: { name: 'michael' } }, { upsert: true })
    .catch(handleError);
  Logger.setLevel('error');
  console.log(res);
  let doc = await db
    .collection('tests')
    .findOne({})
    .catch(handleError);

  console.log(doc);
  process.exit(0);
}

run();

function handleError(e) {
  return console.error(e.message);
}

truncated Output:

...
message: 'executing command [{"ns":"gh-6881.$cmd","cmd":{"findAndModify":"tests","query":{},"new":false,"remove":false,"upsert":true,"update":{"$set":{"name":"michael"}}},"options":{}}] against localhost:27017',
...
{ value: null,
  lastErrorObject:
   { updatedExisting: false,
     n: 1,
     upserted: 5b77a23cd1326ce227b686a1 },
  ok: 1 }
{ _id: 5b77a23cd1326ce227b686a1, name: 'michael' }

Same here. I got this warning on application start:

(node:9856) DeprecationWarning: collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.
(node:9856) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.
(node:9856) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.

If you find deprecation warning annoying, as a _temporary_ workaround, you can start node.js process in cli with --no-deprecation to suppress the warning. It's _not recommended_ to do so though.

with mine:

 (node:1) DeprecationWarning: collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.
 (node:1) DeprecationWarning: collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead.
(node:1) DeprecationWarning: collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.
 (node:1) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
(node:1) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.
(node:1) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.

love package-lock.json more than ever...

There are several workarounds to get around these deprecation warnings:

1) Re: findOneAndUpdate() and findAndModify() deprecation, use mongoose.set('useFindAndModify', false);
2) Re: remove() deprecation, switch to using deleteOne() or deleteMany() depending on if you only want to delete one doc
3) Re: update() deprecation, replace with updateMany()

We'll add some docs to help people clean up these deprecation warnings, and make some internal changes so mongoose doesn't cause one of these deprecation warnings.

Maybe we need to update all deprecated method and remove useFindAndModify options in the next major release?

I'd be in favour of this 👍

Does mongoose already have support for the new methods, deleteOne(), deleteMany(), updateMany() etc?

+1
same warning. we need to wait for new driver.

so like, right now we have to ignore those warnings? i mean i am trying to create api, where i need to get everything from db and whenever i call collection.find().then()....etc it gives me same warning. what can i do to replace that find() method?

If you're just bothered by the warnings, you can probably disable deprecation notices in Node (see Fonger's comment above), or you can revert back to an older version of Mongoose.

So what I need to do?

Got this warning message from mongoose each time i run a find query. Going to ignore it till after the next update from the mongoose team.

(node:15500) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.

The fix for the fields deprecation warning will be in 5.2.10, you won't see it anymore. To clean up the other deprecation warnings, follow the instructions in this comment: https://github.com/Automattic/mongoose/issues/6922#issue-354147871

Thanks for writing this doc https://mongoosejs.com/docs/deprecations.html

Re: findOneAndUpdate() and findAndModify() deprecation, the only current (5.2.17) workaround is to set:

mongoose.set('useFindAndModify', false);

is that true?

I'm using Model.findByIdAndUpdate() and Model.findOneAndUpdate()

I assume the underlying mongo db driver functions being used by mongoose will be / should be updated at some point.
Would be I be right?

+1 I am having same deprecation warning for using Model.findByIdAndUpdate();

I am using following verisions:

  • mongodb: 3.1.4
  • mongoose: 5.2.16

Any news on this ?

@gianpaj yes mongoose.set('useFindAndModify', false) is the only current workaround for the findAndModify deprecation warning. My guess is that the underlying call to collection.findAndModify() will go away in [email protected]. @vkarpov15 does that sound about right? or is it too early to commit to a time frame?

@daniyalawan check out the docs here the 'useFindAndModify' option applies to you if you call findOneAndUpdate in your code ( this extends to findByIdAndUpdate because it calls findOneAndUpdate internally ).

@Sastidar what issue(s) are you having after upgrading to [email protected]? All deprecation warnings should be addressed in these docs

@lineus @gianpaj yep the need for the useFindAndModify option will go away with Mongoose 6.0.0. No timeframe for when we will release Mongoose 6.

Regarding the deprecation warning - Will mongoose be phasing out the ability to use the findByIdAndUpdate method or will the underlying findAndModify just be phased out without killing my implementation?

I'm basically asking if I change all of my findByIdAndUpdate to findOneAndUpdate before I have a larger codebase.

@gianpaj yes mongoose.set('useFindAndModify', false) is the only current workaround for the findAndModify deprecation warning. My guess is that the underlying call to collection.findAndModify() will go away in [email protected]. @vkarpov15 does that sound about right? or is it too early to commit to a time frame?

@daniyalawan check out the docs here the 'useFindAndModify' option applies to you if you call findOneAndUpdate in your code ( this extends to findByIdAndUpdate because it calls findOneAndUpdate internally ).

@Sastidar what issue(s) are you having after upgrading to [email protected]? All deprecation warnings should be addressed in these docs

{new: true} will not work if i use mongoose.set('useFindAndModify', false). any other option?

@anks333 the following example works for me. Can you modify it to show { new: true } not working?

6880.js

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

const assert = require('assert');
const mongoose = require('mongoose');
mongoose.set('useFindAndModify', false);
const { Schema, connection} = mongoose;
const DB = '6880';
const URI = `mongodb://localhost:27017/${DB}`;
const OPTS = { family: 4, useNewUrlParser: true };

const schema = new Schema({
  name: String
});

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

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

async function run() {
  await mongoose.connect(URI, OPTS);
  await connection.dropDatabase();
  const doc = await Test.create(test);
  assert.ok(doc);
  const cond = {};
  const update = { name: 'test2' };
  const options = { new: true };
  const updated = await Test.findOneAndUpdate(cond, update, options);
  assert.strictEqual(updated.name, 'test2');
  console.log('All Assertions Pass.');
  await connection.close();
}

run();

Output:

issues: ./6880.js
All Assertions Pass.
issues:

@LBWright we have no intention of dropping support for findByIdAndUpdate, we will just swap out the underlying findAndModify without breaking the API

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

Was this page helpful?
0 / 5 - 0 ratings