【问题标题】:auto increment ids in mongoose猫鼬中的自动增量ID
【发布时间】:2023-03-19 05:23:01
【问题描述】:

如何在 mongoose 中设置自动增量 ID?我希望我的 id 以 1、2、3、4 开头,而不是 mongodb 为您创建的奇怪的 id 数字?

这是我的架构:

var PortfolioSchema = mongoose.Schema({
    url: String,
    createTime: { type: Date, default: Date.now },
    updateTime: { type: Date, default: Date.now },
    user: {type: Schema.Types.ObjectId, ref: 'User'}
});

【问题讨论】:

    标签: mongodb mongoose mongodb-query


    【解决方案1】:

    使用猫鼬自动增量: https://github.com/codetunnel/mongoose-auto-increment

    var mongoose = require('mongoose');
    var autoIncrement = require('mongoose-auto-increment');
    var connection = ....;
    autoIncrement.initialize(connection);
    
    var PortfolioSchema = new mongoose.Schema({
        url: String,
        createTime: { type: Date, default: Date.now },
        updateTime: { type: Date, default: Date.now },
        user: {type: Schema.Types.ObjectId, ref: 'User'}
    });
    
    //Auto-increment
    PortfolioSchema.plugin(autoIncrement.plugin, { model: 'Portfolio' });
    
    module.exports = mongoose.model('Portfolio', PortfolioSchema);
    

    或者,如果您更喜欢使用附加字段而不是覆盖 _id,只需添加该字段并将其列在自动增量初始化中:

    var PortfolioSchema = new mongoose.Schema({
        portfolioId: {type: Number, required: true},
        url: String,
        createTime: { type: Date, default: Date.now },
        updateTime: { type: Date, default: Date.now },
        user: {type: Schema.Types.ObjectId, ref: 'User'}
    });
    
    //Auto-increment
    PortfolioSchema.plugin(autoIncrement.plugin, { model: 'Portfolio', field: 'portfolioId' });
    

    【讨论】:

    【解决方案2】:

    如果你想在_id 中有一个递增的数值,那么基本过程是你需要一些东西来从某处的商店返回该值。一种方法是使用 MongoDB 本身来存储数据,这些数据包含每个集合的 _id 值的计数器,这在手册本身的 Create and Auto-Incrementing Sequence Field 下进行了描述。

    然后,当您创建每个新项目时,您使用实现的函数来获取该“计数器”值,并将其用作文档中的 _id

    当在这里覆盖默认行为时,猫鼬要求您同时指定 _id 并且它的类型明确地使用 _id: Number 之类的东西,并且您告诉它不再自动尝试使用 @ 提供 ObjectId 类型987654330@ 作为架构的一个选项。

    这是一个实际的工作示例:

    var async = require('async'),
        mongoose = require('mongoose'),
        Schema = mongoose.Schema;
    
    mongoose.connect('mongodb://localhost/test');
    
    var counterSchema = new Schema({
      "_id": String,
      "counter": { "type": Number, "default": 1 }
    },{ "_id": false });
    
    counterSchema.statics.getNewId = function(key,callback) {
      return this.findByIdAndUpdate(key,
        { "$inc": { "counter": 1 } },
        { "upsert": true, "new": true },
        callback
      );
    };
    
    var sampleSchema = new Schema({
      "_id": Number,
      "name": String
    },{ "_id": false });
    
    var Counter = mongoose.model( 'Counter', counterSchema ),
        ModelA = mongoose.model( 'ModelA', sampleSchema ),
        ModelB = mongoose.model( 'ModelB', sampleSchema );
    
    
    async.series(
      [
        function(callback) {
          async.each([Counter,ModelA,ModelB],function(model,callback) {
            model.remove({},callback);
          },callback);
        },
        function(callback) {
          async.eachSeries(
            [
              { "model": "ModelA", "name": "bill" },
              { "model": "ModelB", "name": "apple" },
              { "model": "ModelA", "name": "ted" },
              { "model": "ModelB", "name": "oranage" }
            ],
            function(item,callback) {
              async.waterfall(
                [
                  function(callback) {
                    Counter.getNewId(item.model,callback);
                  },
                  function(counter,callback) {
                    mongoose.model(item.model).findByIdAndUpdate(
                      counter.counter,
                      { "$set": { "name": item.name } },
                      { "upsert": true, "new": true },
                      function(err,doc) {
                        console.log(doc);
                        callback(err);
                      }
                    );
                  }
                ],
                callback
              );
            },
            callback
          );
        },
        function(callback) {
          Counter.find().exec(function(err,result) {
            console.log(result);
            callback(err);
          });
        }
      ],
      function(err) {
        if (err) throw err;
        mongoose.disconnect();
      }
    );
    

    为了方便起见,它在模型上实现了一个静态方法.getNewId(),它只是描述性地包装了.findByIdAndUpdate() 中使用的主要函数。如手册页部分所述,这是.findAndModify() 的一种形式。

    这样做的目的是它将在 Counter 模型集合中查找特定的“键”(实际上还是 _id)并执行操作以“增加”该键的计数器值并返回修改后的文档。 “upsert”选项也有助于这一点,因为如果请求的“key”尚不存在文档,则将创建它,否则该值将通过$inc递增,并且始终如此,默认值为1.

    这里的例子表明两个计数器是独立维护的:

    { _id: 1, name: 'bill', __v: 0 }
    { _id: 1, name: 'apple', __v: 0 }
    { _id: 2, name: 'ted', __v: 0 }
    { _id: 2, name: 'oranage', __v: 0 }
    [ { _id: 'ModelA', __v: 0, counter: 2 },
      { _id: 'ModelB', __v: 0, counter: 2 } ]
    

    首先列出创建的每个文档,然后显示“计数器”集合的结束状态,该集合保存了请求的每个键的最后使用值。

    另请注意,这些“奇怪的数字”有一个特定的目的,即始终保证其唯一性并且始终按顺序递增。请注意,他们这样做无需再次访问数据库即可安全地存储和使用递增的数字。所以这应该值得考虑。

    【讨论】:

    • 如果不是回调地狱,我会更加全心全意地投票:)
    猜你喜欢
    • 2015-04-06
    • 2016-10-16
    • 2021-07-17
    • 2014-06-10
    • 2020-11-24
    • 2018-12-12
    相关资源
    最近更新 更多