This is what I’ve done:
Every collection needing an “autoincrement” gets an extra document added: {_id: "autoincrement", value: 0}
. I usually put the insert(s) in the server-side Meteor.startup()
:
Meteor.startup(function() {
try {
MyCollection.insert({_id: 'autoincrement', value: 0});
} catch(err) {
// Will always get here once the doc's in place, so just ignore
}
try {
AnotherCollection.insert({_id: 'autoincrement', value: 0});
} catch(err) {
// Will always get here once the doc's in place, so just ignore
}
});
Define a helper function to do the autoincrement on a collection (note the node syntax):
const doAutoincrement = function(collection, callback) {
collection.rawCollection().findAndModify({
_id: 'autoincrement'
}, [], {
$inc: {
value: 1
}
}, {
'new': true
}, callback);
}
and define a (synchronous) function to get the next autoincrement value for a collection:
const nextAutoincrement = function(collection) {
return Meteor.wrapAsync(doAutoincrement)(collection).value;
}
Then, when I want the next autoincrement value:
let nextValue = nextAutoincrement(MyCollection); // 1
nextValue = nextAutoincrement(MyCollection); // 2
nextValue = nextAutoincrement(MyCollection); // 3
let anotherNextValue = nextAutoincrement(AnotherCollection); // 1
Using findAndModify
is atomic and is safe even when multiple server instances are being used.