首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mongo / Mongoose自动递增单据号

Mongo / Mongoose自动递增单据号
EN

Stack Overflow用户
提问于 2013-01-22 16:23:56
回答 4查看 25.1K关注 0票数 8

我的应用程序有几个用户,每个用户都有文档。每个文档都需要有一个序列号,它可能类似于: 2013-1,2013-2 (年份和序列号),或者可能只是一个简单的数字: 1,2,3……

目前,我是在创建Mongoose docuemnt时从用户设置中分配序列号的。根据该序列号和用户设置中的编号格式,我将生成最终的文档编号。

我意识到的是,当同时创建两个文档时,它们将获得完全相同的编号,因为我在保存文档后立即在设置中递增序列号。但我在创建(尚未保存)文档时分配了序列号,因此两个文档的序列号将完全相同。

我显然需要一种方法来处理这个序列号在保存时自动递增的问题……

如何确保此数字是唯一的,并自动递增/生成?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-01-22 21:12:22

@emre和@WiredPraire为我指明了正确的方向,但我想为我的问题提供一个完全兼容Mongoose的答案。我最终得到了以下解决方案:

代码语言:javascript
复制
var Settings = new Schema({
  nextSeqNumber: { type: Number, default: 1 }
});

var Document = new Schema({
  _userId: { type: Schema.Types.ObjectId, ref: "User" },
  number: { type: String }
});

// Create a compound unique index over _userId and document number
Document.index({ "_userId": 1, "number": 1 }, { unique: true });

// I make sure this is the last pre-save middleware (just in case)
Document.pre('save', function(next) {
  var doc = this;
  // You have to know the settings_id, for me, I store it in memory: app.current.settings.id
  Settings.findByIdAndUpdate( settings_id, { $inc: { nextSeqNumber: 1 } }, function (err, settings) {
    if (err) next(err);
    doc.number = settings.nextSeqNumber - 1; // substract 1 because I need the 'current' sequence number, not the next
    next();
  });
});

请注意,使用此方法无法要求模式中的数字路径,也没有点,因为它是自动添加的。

票数 12
EN

Stack Overflow用户

发布于 2014-10-29 08:51:08

您可以通过以下方式实现此目的:

  1. create sequence generator,这只是另一个保存最后一个数字计数器的文档。
  2. 使用mongoose中间件来更新自动递增所需字段。

下面是一个正在运行且经过测试的todo应用程序示例。

代码语言:javascript
复制
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/todoApp');

// Create a sequence
function sequenceGenerator(name){
  var SequenceSchema, Sequence;

  SequenceSchema = new mongoose.Schema({
    nextSeqNumber: { type: Number, default: 1 }
  });

  Sequence = mongoose.model(name + 'Seq', SequenceSchema);

  return {
    next: function(callback){
      Sequence.find(function(err, data){
        if(err){ throw(err); }

        if(data.length < 1){
          // create if doesn't exist create and return first
          Sequence.create({}, function(err, seq){
            if(err) { throw(err); }
            callback(seq.nextSeqNumber);
          });
        } else {
          // update sequence and return next
          Sequence.findByIdAndUpdate(data[0]._id, { $inc: { nextSeqNumber: 1 } }, function(err, seq){
            if(err) { throw(err); }
            callback(seq.nextSeqNumber);
          });
        }
      });
    }
  };
}

// sequence instance
var sequence = sequenceGenerator('todo');

var TodoSchema = new mongoose.Schema({
  name: String,
  completed: Boolean,
  priority: Number,
  note: { type: String, default: '' },
  updated_at: { type: Date, default: Date.now }
});

TodoSchema.pre('save', function(next){
  var doc = this;
  // get the next sequence
  sequence.next(function(nextSeq){
    doc.priority = nextSeq;
    next();
  });
});

var Todo = mongoose.model('Todo', TodoSchema);

您可以在节点控制台进行测试,如下所示

代码语言:javascript
复制
function cb(err, data){ console.log(err, data); }
Todo.create({name: 'hola'}, cb);
Todo.find(cb);

随着每个新创建的对象,您将看到优先级增加。干杯!

票数 3
EN

Stack Overflow用户

发布于 2013-01-22 16:40:10

这段代码取自MongoDB手册,它实际上描述了如何使_id字段自动递增。但是,它可以应用于任何领域。您想要的是在插入文档之后检查插入的值是否存在于数据库中。如果已经插入,请重新递增该值,然后再次尝试插入。通过这种方式,您可以检测Dublic值并重新递增它们。

代码语言:javascript
复制
while (1) {

    var cursor = targetCollection.find( {}, { f: 1 } ).sort( { f: -1 } ).limit(1);

    var seq = cursor.hasNext() ? cursor.next().f + 1 : 1;

    doc.f = seq;

    targetCollection.insert(doc);

    var err = db.getLastErrorObj();

    if( err && err.code ) {
        if( err.code == 11000 /* dup key */ )
            continue;
        else
            print( "unexpected error inserting data: " + tojson( err ) );
    }

    break;
}

在本例中,f是文档中要自动递增的字段。要做到这一点,您需要使您的字段唯一,这可以通过索引来完成。

代码语言:javascript
复制
db.myCollection.ensureIndex( { "f": 1 }, { unique: true } )
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14454271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档