mongoose自动增量

IT技术 javascript mongodb mongoose auto-increment
2021-01-22 02:15:57

根据this mongodb article,可以自动增加字段,我希望使用计数器收集方式。

该示例的问题是我没有成千上万的人使用 mongo 控制台在数据库中输入数据。相反,我正在尝试使用mongoose。

所以我的架构看起来像这样:

var entitySchema = mongoose.Schema({
  testvalue:{type:String,default:function getNextSequence() {
        console.log('what is this:',mongoose);//this is mongoose
        var ret = db.counters.findAndModify({
                 query: { _id:'entityId' },
                 update: { $inc: { seq: 1 } },
                 new: true
               }
        );
        return ret.seq;
      }
    }
});

我在同一个数据库中创建了 counters 集合,并添加了一个 _id 为“entityId”的页面。从这里我不确定如何使用mongoose来更新该页面并获得递增的数字。

没有计数器模式,我希望它保持这种状态,因为这实际上并不是应用程序使用的实体。它应该只用于模式中以自动增加字段。

6个回答

以下是如何在 Mongoose 中实现自动递增字段的示例:

var CounterSchema = Schema({
    _id: {type: String, required: true},
    seq: { type: Number, default: 0 }
});
var counter = mongoose.model('counter', CounterSchema);

var entitySchema = mongoose.Schema({
    testvalue: {type: String}
});

entitySchema.pre('save', function(next) {
    var doc = this;
    counter.findByIdAndUpdate({_id: 'entityId'}, {$inc: { seq: 1} }, function(error, counter)   {
        if(error)
            return next(error);
        doc.testvalue = counter.seq;
        next();
    });
});
你可以在声明 Schema 后把它放在同一个文件中
2021-03-16 02:15:57
当有多个并发请求时,您能告诉我您的解决方案是否有效?如果是,那么如何?
2021-03-26 02:15:57
@realisationfindByIdAndUpdate根据mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate发出的mongodbfindAndModify原子的。
2021-03-31 02:15:57
我意识到这有点旧,但是,当您对 entitySchema 进行任何更新(例如更新状态)时,这不会增加计数器,从而使对 uniqe id 的所有引用都无用吗?也许先检查 isNew。
2021-04-01 02:15:57
我在哪里可以放这个 entitySchema.pre('save', callback); 如果我将每个模型都放在模型文件夹中的单独文件中?
2021-04-07 02:15:57

您可以mongoose-auto-increment按如下方式使用包:

var mongoose      = require('mongoose');
var autoIncrement = require('mongoose-auto-increment');

/* connect to your database here */

/* define your CounterSchema here */

autoIncrement.initialize(mongoose.connection);
CounterSchema.plugin(autoIncrement.plugin, 'Counter');
var Counter = mongoose.model('Counter', CounterSchema);

您只需要初始化autoIncrement一次。

该软件包不再维护。截至 2020 年 4 月,mongoose 自动增量的最佳维护和文档包是mongoose-sequence.
2021-04-03 02:15:57

投票最多的答案不起作用。这是修复:

var CounterSchema = new mongoose.Schema({
    _id: {type: String, required: true},
    seq: { type: Number, default: 0 }
});
var counter = mongoose.model('counter', CounterSchema);

var entitySchema = mongoose.Schema({
    sort: {type: String}
});

entitySchema.pre('save', function(next) {
    var doc = this;
    counter.findByIdAndUpdateAsync({_id: 'entityId'}, {$inc: { seq: 1} }, {new: true, upsert: true}).then(function(count) {
        console.log("...count: "+JSON.stringify(count));
        doc.sort = count.seq;
        next();
    })
    .catch(function(error) {
        console.error("counter error-> : "+error);
        throw error;
    });
});

选项的参数为您提供了更新的结果,如果它不存在,它会创建一个新文档。你可以在这里查看官方文档。

如果您需要排序索引,请查看此文档

根据示例: app.post(...) - 我想在何处使用自动增量 - 我必须在何处插入此代码以及它如何调用?
2021-03-22 02:15:57
findByIdAndUpdateAsync不是mongoose的文档中的方法。甚至答案中的链接也指向findByIdAndUpdate.
2021-04-07 02:15:57

所以结合多个答案,这就是我最终使用的:

counterModel.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

const counterSchema = new Schema(
  {
  _id: {type: String, required: true},
  seq: { type: Number, default: 0 }
  }
);

counterSchema.index({ _id: 1, seq: 1 }, { unique: true })

const counterModel = mongoose.model('counter', counterSchema);

const autoIncrementModelID = function (modelName, doc, next) {
  counterModel.findByIdAndUpdate(        // ** Method call begins **
    modelName,                           // The ID to find for in counters model
    { $inc: { seq: 1 } },                // The update
    { new: true, upsert: true },         // The options
    function(error, counter) {           // The callback
      if(error) return next(error);

      doc.id = counter.seq;
      next();
    }
  );                                     // ** Method call ends **
}

module.exports = autoIncrementModelID;

我的模型.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

const autoIncrementModelID = require('./counterModel');

const myModel = new Schema({
  id: { type: Number, unique: true, min: 1 },
  createdAt: { type: Date, default: Date.now },
  updatedAt: { type: Date },
  someOtherField: { type: String }
});

myModel.pre('save', function (next) {
  if (!this.isNew) {
    next();
    return;
  }

  autoIncrementModelID('activities', this, next);
});

module.exports = mongoose.model('myModel', myModel);

注意力!

正如hammerbotdan-dascalescu指出的那样,如果您删除文档,这将不起作用

如果您插入 3 个带有 id 的文档12并且3- 您删除2并插入另一个新文档,它将3作为已使用的 id !

如果您永远不会删除文档,请执行以下操作:

我知道这已经有很多答案,但我会分享我的解决方案,它是 IMO 简短易懂的:

// Use pre middleware
entitySchema.pre('save', function (next) {

    // Only increment when the document is new
    if (this.isNew) {
        entityModel.count().then(res => {
            this._id = res; // Increment count
            next();
        });
    } else {
        next();
    }
});

确保entitySchema._id具有type:Number. mongoose版本:5.0.1.

不要认为它适用于所有情况,但它解决了我的问题。
2021-03-17 02:15:57
如果某些文档在某个时候从表中删除,IMO 这会中断......但无论如何,它也适用于我的用例
2021-03-19 02:15:57
正如@Hammerbot 所建议的,获取下一个序列值的文档计数是非常危险的,出于同样的原因mongoose-sequence的作者解释了
2021-03-22 02:15:57