Mongoose: mongodb 中弃用的收集方法

创建于 2018-08-17  ·  28评论  ·  资料来源: Automattic/mongoose

您要请求功能还是报告错误

漏洞

当前的行为是什么?

Model.findByIdAndUpdate() 正在为 mongodb 发出弃用警告 - 它已弃用 collection.findAndModify。 Mongodb 建议使用 findOneAndUpdate、findOneAndReplace 或 findOneAndDelete。

collection.ensureIndex 也被弃用 - mongodb 建议使用 createIndexes 代替。

如果当前行为是错误,请提供重现的步骤。

使用 Model.findByIdAndUpdate / findOneAndUpdate 更改文档会返回这些弃用警告。

预期的行为是什么?

没有弃用警告!

请提及您的 node.js、mongoose 和 MongoDB 版本。

节点 v10.8.0
mongodb v3.6.2
猫鼬 v5.2.9

最有用的评论

同样在这里。 我还得到“查找选项 [fields] 已弃用,将在以后的版本中删除。”

所有28条评论

同样在这里。 我还得到“查找选项 [fields] 已弃用,将在以后的版本中删除。”

(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.

这是我得到的其他一些

与 #6165 相关,可以在CI 测试中重现

您可以useFindAndModify指定为 false以防止出现部分弃用消息。 IMO 现在应该默认为 false 。

mongoose.set('useFindAndModify', false);

警告:未经适当测试,请勿在生产中将此选项设置为 false

但是,其他已弃用的方法,如ensureIndex(es)update仍然需要被新的 API 取代。 将此选项设置为 false 不会解决此问题。
也许我们需要更新所有不推荐使用的方法并在下一个主要版本中删除useFindAndModify选项?

笔记:
只有 MongoDB 3.2+ 支持 findOneAndUpdate 系列查询,但底层的[email protected]库仍然使用 findAndModify polyfill 以保持与 2.6 的兼容性,因此将useFindAndModify默认设置为 false 并不会真正放弃当前对 MongoDB 3.0 的支持。

然而,这种兼容性肯定会在它们自[email protected] (很久以前)被标记为已弃用后很快就会中断,现在甚至会抛出警告消息。

因此,我建议 mongoose (6.x) 的下一个主要版本弃用 MongoDB 3.0 支持并采用所有新的 API。 此外,半年前,MongoDB 3.0 已于 2018 年 2 月报废。

有什么想法吗?

那么……为什么会这样? 是否需要等到下一个 mongoose 主要版本发布?

@lpiVasquez这是因为文档说 mongoose 5.x support MongoDB Server 3.0

现在只使用新的 API 是安全的,因为底层 API 仍在为我们处理这个问题。 但是,一旦底层库改变了这种行为,它就不起作用了,我们在升级底层库时需要非常小心。

我的意思不是忽略这个问题,而是在下一个版本 5.3 中放弃对 MongoDB Server 3.0 的支持。 至少不要闯入5.2。 不过只是我的看法。

@IpiVasquez

如果通过,

为什么会这样?

你的意思是,

为什么 mongodb 不推荐使用这些 API

Mongodb 有一个计划来使各种驱动程序 API 更加一致。 这记录在 mongodb crud 规范中

是否需要等到下一个 mongoose 主要版本发布?

如果我们坚持semver 规范,那么任何破坏 API 的事情都应该发生在主要版本中,比如@6.0.0 ,而不是像@5.3.0这样的次要版本或像@5.2.10这样的补丁版本@5.2.10

回顾原生驱动的历史,我不希望他们在驱动 v4 之前删除这些方法。

同时,我认为到目前为止我看到的大多数弃用警告都可以通过不调用弃用的方法在用户空间中得到缓解。 我猜这些方法中的大多数都会在 mongoose @6.0.0中被删除。

我认为我们要尽快在猫鼬中处理的两个主要问题是在查询选项中将projections替换为fields (至少可以追溯到服务器版本 3.0.15 )并且可能会发生变化@Fonger描述的useFindAndModify的默认值,带有一个附录:

当您连接到 3.2 之前的服务器时,本机驱动程序中的 findOneAndUpdate 将在内部为您调用 findAndModify(没有弃用警告),因此 mongoose 中的findOneAndUpdate仍然适用于 mongodb pre 3.2 和useFindAndModify: false如本例所示:

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

输出:

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

您也可以使用本机驱动程序来演示这一点,如下所示:

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

截断输出:

...
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' }

同样在这里。 我在应用程序启动时收到此警告:

(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.

如果您发现弃用警告令人讨厌,作为_temporary_解决方法,您可以在 cli 中使用--no-deprecation启动 node.js 进程以抑制警告。 但_不推荐_这样做。

和我的:

 (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.

比以往任何时候都更喜欢 package-lock.json...

有几种解决方法可以绕过这些弃用警告:

1) 回复: findOneAndUpdate()findAndModify()弃用,使用mongoose.set('useFindAndModify', false);
2)回复: remove()弃用,切换到使用deleteOne()deleteMany()取决于您是否只想删除一个文档
3) 回复: update()弃用,替换为updateMany()

我们将添加一些文档来帮助人们清理这些弃用警告,并进行一些内部更改,以便 mongoose 不会导致这些弃用警告之一。

也许我们需要在下一个主要版本中更新所有不推荐使用的方法并删除 useFindAndModify 选项?

我赞成这个👍

mongoose 是否已经支持新方法deleteOne()deleteMany()updateMany()等?

+1
同样的警告。 我们需要等待新的驱动程序。

就像,现在我们必须忽略这些警告? 我的意思是我正在尝试创建 api,我需要从 db 获取所有内容,每当我调用 collection.find().then()....等时,它都会给我同样的警告。 我能做些什么来替换那个 find() 方法?

如果您只是对警告感到困扰,您可以禁用 Node 中的弃用通知(请参阅上面 Fonger 的评论),或者您可以恢复到旧版本的 Mongoose。

那么我需要做什么?

每次我运行查找查询时都会收到来自猫鼬的警告消息。 在猫鼬团队的下一次更新之前将忽略它。

(node:15500) DeprecationWarning: collection.find 选项 [fields] 已弃用,将在以后的版本中删除。

fields弃用警告的修复程序将在 5.2.10 中,您将不会再看到它。 要清除其他弃用警告,请按照此评论中的说明进行操作: https ://github.com/Automattic/mongoose/issues/6922#issue -354147871

感谢您编写此文档https://mongoosejs.com/docs/deprecations.html

回复: findOneAndUpdate()findAndModify()弃用,当前唯一的( 5.2.17 )解决方法是设置:

mongoose.set('useFindAndModify', false);

真的吗?

我正在使用Model.findByIdAndUpdate()Model.findOneAndUpdate()

我假设 mongoose 使用的底层 mongo db 驱动程序函数将/应该在某个时候更新。
我会是对的吗?

+1 我对使用 Model.findByIdAndUpdate(); 有同样的弃用警告;

我正在使用以下版本:

  • 蒙哥达:3.1.4
  • 猫鼬:5.2.16

有这方面的消息吗?

@gianpajmongoose.set('useFindAndModify', false)是 findAndModify 弃用警告的唯一当前解决方法。 我的猜测是对collection.findAndModify()的潜在调用将在[email protected] 中消失。 @vkarpov15听起来对吗? 还是现在承诺时间框架还为时过早?

@daniyalawan在此处查看文档,如果您在代码中调用findOneAndUpdate ,则“useFindAndModify”选项适用于您(这扩展到 findByIdAndUpdate ,因为它在内部调用 findOneAndUpdate )。

@Sastidar升级到 [email protected] 后你有什么问题 所有弃用警告都应在这些文档中解决

@lineus @gianpaj是的,对 useFindAndModify 选项的需求将随着 Mongoose 6.0.0 消失。 我们何时发布 Mongoose 6 没有时间表。

关于弃用警告 - mongoose 会逐步淘汰使用findByIdAndUpdate方法的能力,还是会逐步淘汰底层的findAndModify而不杀死我的实现?

我基本上是在问我是否在拥有更大的代码库之前将所有findByIdAndUpdate更改为findOneAndUpdate

@gianpajmongoose.set('useFindAndModify', false)是 findAndModify 弃用警告的唯一当前解决方法。 我的猜测是对collection.findAndModify()的潜在调用将在[email protected] 中消失。 @vkarpov15听起来对吗? 还是现在承诺时间框架还为时过早?

@daniyalawan在此处查看文档,如果您在代码中调用findOneAndUpdate ,则“useFindAndModify”选项适用于您(这扩展到 findByIdAndUpdate ,因为它在内部调用 findOneAndUpdate )。

@Sastidar升级到 [email protected] 后你有什么问题 所有弃用警告都应在这些文档中解决

{new: true}如果我使用mongoose.set('useFindAndModify', false) $ 将不起作用。 还有其他选择吗?

@anks333以下示例适用于我。 你能修改它以显示{ new: true }不工作吗?

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

输出:

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

@LBWright我们无意放弃对 findByIdAndUpdate 的支持,我们只会在不破坏 API 的情况下换掉底层的 findAndModify

(节点:10767)DeprecationWarning:collection.ensureIndex 已弃用。 请改用 createIndexes。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

weisjohn picture weisjohn  ·  3评论

lukasz-zak picture lukasz-zak  ·  3评论

ArThoX picture ArThoX  ·  3评论

simonxca picture simonxca  ·  3评论

gustavomanolo picture gustavomanolo  ·  3评论