如果你想在_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 } ]
首先列出创建的每个文档,然后显示“计数器”集合的结束状态,该集合保存了请求的每个键的最后使用值。
另请注意,这些“奇怪的数字”有一个特定的目的,即始终保证其唯一性并且始终按顺序递增。请注意,他们这样做无需再次访问数据库即可安全地存储和使用递增的数字。所以这应该值得考虑。