【问题标题】:Mongoose Changing Schema Format猫鼬改变模式格式
【发布时间】:2012-12-26 14:14:15
【问题描述】:

我们正在快速开发一个使用 Mongoose 的应用程序,并且我们的架构经常发生变化。我似乎无法找出正确的方法来更新现有文档的架构,而不是将它们吹走并从头开始完全重新创建它们。

我遇到了http://mongoosejs.com/docs/api.html#schema_Schema-add,看起来是对的。几乎没有关于如何实际实现这一点的文档,这对于刚接触 MongoDB 的人来说非常困难。

我只想添加一个名为启用的新字段。我的架构定义是:

var sweepstakesSchema = new Schema({
    client_id: {
        type: Schema.Types.ObjectId,
        ref: 'Client',
        index: true
    },
    name: {
        type: String,
        default: 'Sweepstakes',
    },
    design: {
        images: {
            type: [],
            default: []
        },
        elements: {
            type: [],
            default: []
        }
    },
    enabled: {
        type: Boolean,
        default: false
    },
    schedule: {
        start: {
            type: Date, 
            default: Date.now
        },
        end: {
            type: Date,
            default: Date.now
        }
    },
    submissions: {
        type: Number,
        default: 0
    }
});

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    考虑到您的 Mongoose 型号名称为 sweepstakesModel, 此代码会将具有布尔值 false 的 enabled 字段添加到您集合中的所有预先存在的文档中:

    db.sweepstakesModel.find( { enabled : { $exists : false } } ).forEach(
        function (doc) {
            doc.enabled = false;
            db.sweepstakesModel.save(doc);
        }
    )
    

    【讨论】:

      【解决方案2】:

      Mongoose 没有内置任何关于迁移现有文档以符合架构更改的内容。您需要根据需要在自己的代码中执行此操作。在像新的enabled 字段这样的情况下,编写代码可能是最干净的,以便它将丢失的enabled 字段视为设置为false,这样您就不必接触现有的文档。

      就架构更改本身而言,您只需更新您的 Schema 定义,如您所展示的,但是像具有 default 值的新字段这样的更改只会影响未来的新文档。

      【讨论】:

      • 但是像使用默认值的新字段这样的变化只会影响新的文档。 - 我想它也会影响更新的文档吧? (不仅是新的)
      • @Michael 不是,不是。添加具有默认值的新字段将使这些字段出现在现有文档的 mongoose 实例中,但实际上不会将该字段添加到现有文档中,即使您在它们上调用 save。
      • 所以在我将x 添加到具有默认值的架构之后保存以前没有字段x 的文档不会使用x 更新文档吗?我不明白这种设计选择,这是否记录在某处?谢谢
      • @Michael 正确。我不知道它是否在任何地方都有记录,但是当我尝试它时就会发生这种情况。
      • @Michael 很多方法几乎只是对本机 mongodb 驱动程序的传递(例如schema.update)。 find 就是其中之一。
      【解决方案3】:

      我也在寻找类似迁移的东西,但没有找到。作为替代方案,您可以使用默认值。如果一个键有默认值,而该键不存在,它将使用默认值。

      Mongoose Defaults

      在构建文档框架时应用默认值。这意味着如果您创建一个新文档 (new MyModel) 或如果您找到一个现有文档 (MyModel.findById),如果缺少某个键,两者都将具有默认值。

      【讨论】:

        【解决方案4】:

        我遇到了完全相同的问题,发现使用findOneAndUpdate() 而不是调用save 可以让我们更新架构文件,而无需先删除所有旧文档。

        如果需要,我可以发布代码 sn-p。

        【讨论】:

          【解决方案5】:

          您可以使用 mongo shell 来更新特定集合中的现有文档

          db.SweeptakesModel.update({}, {$set: {"enabled": false}}, {upsert:false, multi:true})
          

          【讨论】:

            【解决方案6】:

            除了 Vickar 的建议,这里是用 Javascript (Nodejs) 编写的 Mongoose 示例:

            const mongoose = require('mongoose');
            const SweeptakesModel = mongoose.model(Constants.SWEEPTAKES,sweepstakesSchema);
            SweeptakesModel.find( { enabled : { $exists : false } }).then(
            function(doc){
                   doc.enabled = false;
                   doc.save();
                }
            )
            

            【讨论】:

              【解决方案7】:

              在使用 Node 构建应用程序时,我有一个类似的要求,必须添加到现有架构中,并且只发现这个(很久以前发布的)查询可以提供帮助。

              我通过在架构的原始描述中引入该行然后运行类似于以下行的内容(仅一次)来更新现有记录,从而添加到该架构:

              myModelObject.updateMany( { enabled : { $exists : false } }, { enabled : false } )
              

              'updateMany' 是我想在这里提到的函数。

              【讨论】:

                猜你喜欢
                • 2016-08-05
                • 1970-01-01
                • 2020-09-18
                • 2012-02-02
                • 2019-10-18
                • 2013-05-15
                • 2014-04-01
                • 2021-09-21
                • 2015-05-20
                相关资源
                最近更新 更多