I was just playing around the concepts of sailsjs then I came to know we cannot use auto increments in sails if we are using mongodb as our database. I cannot able to use the auto increments even for the non primary key attributes. Is there any special methods to use auto increments operations for an attribute which is not a primary key? Thanks in advance
If waterline doesn't support it automatically, which is what it seems like, you can do it in the beforeCreate
lifecycle callback of waterline. It is independent of any database adapter.
I would recommend you to take a look at how lifecycle callbacks work for clear understanding. Workflow would be something like following. Before creating any record you would check the count of records of the Model
. Then update the x
field of the records to be created as one more than that found count and pass the batton.
beforeCreate: function(obj, next){
Model.count().exec(function(err, cnt){
if(err) next(err);
else{
obj['x'] = cnt + 1;
next(null);
}
})
}
Counting the records is not the perfect way. You can change the way you like to find the value of auto-incremented value. Purpose of this example is to give you intuition of how it can be done. This is not the exact alternative of autoincrement but it's an effective workaround I guess. Hope it helps you.
There are different strategies, how you can create auto increment sequences with mongo. You can find the general information in the official documentation http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/
Here is an adaptation of the first approach for sails.js waterline, which uses counter collection. First you have to create a Sequence Model and implement a get next method.
module.exports = {
attributes : {
num : {
type : "integer"
},
},
next : function (id, cb) {
Sequence.native(function (err, col) {
col.findAndModify(
{ _id: id },
[['_id', 'asc']],
{$inc: { num : 1 }},
{ new: true, upsert : true}
, function(err, data) {
cb(err, data.value.num);
});
});
},
};
Since waterline doesn't support findAndModify functionality of mongodb, you have to make use of native driver method. It looks bit weird, but it works. More about it here.
And then you can just call the Sequence.next() in the beforeCreate lifecycle callback method of your model to get next auto increment value for the new collection document.
// Model Order, for Example.
module.exports = {
attributes: {
number: {
type: "integer"
},
// other attributes
},
// add auto increment value for "number" before create a document
beforeCreate : function (values, cb) {
// add seq number, use
Sequence.next("order", function(err, num) {
if (err) return cb(err);
values.number = num;
cb();
});
}
// your other methods ...
};
I know it is a bit late, but I just solved it for me and wanted to share.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With