【问题标题】:Mongo's updateMany with rename doesn't update for some fieldsMongo 的 updateMany 重命名不会更新某些字段
【发布时间】:2021-07-30 16:03:20
【问题描述】:

说明

MongoDB 的 updateMany 方法在某些字段上与 $rename 一起使用时不会更新任何文档。

示例

我尝试重命名字段blog.blog_ttileblog.blog_cotnet。我检查了拼写错误,没有。

Example model:

User: {
  name,
  email,
  blog: {
    blog_ttile,
    blog_cotnet
  }
}

代码:

const mongoose = require('mongoose');

const User = mongoose.model('User');

const nameChanges = {
  "blog.blog_ttile": 'blog.title',
  'blog.blog_cotnet': 'blog.content',
};

async function performNameChanges() {
  try {
    const updatedDocuments = await User.updateMany({}, { $rename: nameChanges }); 

    console.log({ updatedDocuments });
  } catch(err) {
    console.error(err);
  }
}

返回:

{ updatedDocuments: { ok: 0, n: 0, nModified: 0 } }

其他详情

某些字段被正确识别。假设在上面的例子中email。但是,当我尝试更新更新的名称时,它不再起作用。有趣的是,它仍然检测到原始名称。

例子

email 重命名为personal_email 有效。之后将personal_email 重命名为email 不会并返回{ ok: 0, n: 0, nModified: 0 }。再次对 email 调用重命名会返回 { n: <total_records>, nModified: 0, ok: 1 },尽管没有文档具有 email

这可能是什么原因造成的?

注意: 这个问题适用于没有 Mongoose 的 MongoDB,使用 db.getCollection("User").updateMany 而不是 User.updateMany

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    我尝试在 MongoDB 中做同样的事情。它按预期工作。在您的情况下,我怀疑 Mongoose 模式是导致这种奇怪行为的原因。 Mongoose Schema 必须具有您要重命名的字段。如果该字段不存在,则返回 nModified 0。模式需要同时具有旧名称和新名称。旧的允许迁移,新的用于代码中的新逻辑。

    你的返回结果是:

    { updatedDocuments: { ok: 0, n: 0, nModified: 0 } }
    

    这怎么可能? n=0?用于查询 {}。只有当您的集合中没有元素时才有可能。 n 表示匹配计数,它必须等于集合中的记录总数。

    将电子邮件重命名为个人电子邮件有效

    在第一次更新您的架构之前没问题。但是在重命名(第一次更新)之后,您应该将架构更新为:

    User: {
      name,
      personal_email,
      blog: {
        blog_tile,
        blog_contnet
      }
    }
    

    在运行第二次更新之前(重命名回电子邮件)。

    【讨论】:

    • 感谢您的回答。这是架构。在运行重命名方法之前,我将架构更新为新字段。在架构中同时包含旧名称和新名称使这项工作有效。
    • 我进行了编辑以描述架构可能导致此问题的原因。它还没有被接受。一旦有关实际原因的详细信息在那里,我会立即将您的答案标记为已接受。
    • 我也遇到了同样的问题,我刚刚将旧的密钥配置插入到 Schema 中并运行了代码,然后就成功了!谢谢。
    【解决方案2】:

    正如另一个答案中所说,这是因为您的猫鼬模式不包含您要重命名的字段。

    除了在迁移时保留旧字段,您还可以在选项中指定strict: false,mongoose 不会丢弃未知路径:

    const mongoose = require('mongoose');
    
    const User = mongoose.model('User');
    
    const nameChanges = {
      "blog.blog_ttile": 'blog.title',
      'blog.blog_cotnet': 'blog.content',
    };
    
    async function performNameChanges() {
      try {
        const updatedDocuments = await User.updateMany(
          {},
          { $rename: nameChanges },
          {
            // Strict allows to update keys that do not exist anymore in the schema
            strict: false,
          }
        ).exec();
    
        console.log({ updatedDocuments });
      } catch(err) {
        console.error(err);
      }
    }
    

    【讨论】:

      【解决方案3】:

      这样使用谢谢你

      
      import { connect } from '../database';
      
      export const renameFileds = async () => {
        const db = connect();
        //let userlist = await db.UserModel.find();
        const updatedDocuments = await db.UserModel.updateMany(
          {},
          { $rename: { image: 'picture' } },
          {
            // Strict allows to update keys that do not exist anymore in the schema
            strict: false,
          }
        ).exec();
      
        console.log({ updatedDocuments });
      };
      renameFileds();
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-29
        • 1970-01-01
        • 2012-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-16
        相关资源
        最近更新 更多