I am newbie to mongoose, I have a mongoose schema like this:
var user = mongoose.Schema({
userID: {
type: String,
required:true
},
seq: {
type: Number,
default: 0
},
firstname: {
type: String
},
lastname: {
type: String
},
dob: {
type: String
},
email: {
type: String,
required: true
},
username: {
type: String,
required: true
},
displayname: {
type: String
},
password: {
type: String,
required: true
},
mobile: {
type: String
},
profilePic: {
type: String
},
city: {
type: String
},
gender: {
type: String
},
profileType: {
type: String,
required: true
},
profileId: {
type: String
},
isActive: {
type: Number
},
ageVerified: {
type: String
},
ipAddress: {
type: String
},
key: {
type: String
},
osType: {
type: String
},
osVersion: {
type: String
},
deviceName: {
type: String
},
joinedDate: {
type: String
},
connectedAccounts: [{
profileType: {
type: String
},
profileId: {
type: String
},
email: {
type: String
}
}]
}, {collection: 'user'});
Please note the userID is an auto increment number field, for inserting value am using the mongoose query like:
new user(contents).save(function (err,doc){};
'contents' is a object, which contain data for all the field except userID, here my question is how to insert value for the userID(autoincrement number) while inserting records for other fields? And I refer this linkto set the auto increment value... But I don't know how to use this in mongoose?
Following the MongoDB tutorial, Create an Auto-Incrementing Sequence Field, you need to first create a separate counters
collection to track the last number sequence used. The _id
field contains the sequence name i.e. the userID
field in the user collection and the seq
field contains the last value of the sequence.
To start with, insert into the counters collection the initial value for the userID
:
db.counter.insert(
{
"_id": "userID",
"seq": 0
}
)
Having populated the counters collection, generate its schema in Mongoose:
var counterSchema = mongoose.Schema({
"_id": { "type": String, "required": true },
"seq": { "type": Number, "default": 0 }
});
var counter = mongoose.model('counter', counterSchema);
Then redefine your user schema so that when you save a user model it first calls the counter model's findByIdAndUpdate()
method to atomically increment the seq value and return this new value which can then be used as the next userID
value:
var userSchema = mongoose.Schema({
"userID": { "type": String, "required": true },
"firstname": { "type": String },
"lastname": { "type": String },
// other properties ...
}, { "collection": "user" }
);
userSchema.pre("save", function (next) {
var doc = this;
counter.findByIdAndUpdate(
{ "_id": "userID" },
{ "$inc": { "seq": 1 } }
, function(error, counter) {
if(error) return next(error);
doc.userID = counter.seq.toString();
next();
});
});
Considering that the logic of schema.findByIdAndUpdate
is "return the current value and THEN increment it", you can also use @chridam's solution with the following edit:
var counter = mongoose.model('counter', counterSchema);
userSchema.pre("save", function (next) {
var doc = this;
counter.findByIdAndUpdate(
{ "_id": "userID" },
{ "$inc": { "seq": 1 } }
, function(error, c /*counter*/) {
if(error)
return next(error);
else if(!c) {
c = new counter({ _id: "userID" }, { $inc: { seq: 1 } };
c.save(function() {
doc.userID = (c.seq - 1) + '';
next();
});
} else {
doc.userID = counter.seq.toString();
next();
}
});
});
Please, note that this solutions makes your code function from scratch WITHOUT forcing you to initialize the DB.
The tricks lies in the first round of the loop. counter
is undefined, so you need to initialize it, but if you initialize it equal to 0, next tick the code tries to assign userID=0
again!
This is because on one hand there is the logic of schema.findByIdAndUpdate
that reads-first the value and then increments it, on the other hand you need a logic that assigns-first the value though.
You can join these two logics by making the algorithm skip the first step and setting variable values as above.
Notes: counterSchema
is the same as chridam's:
counterSchema = mongoose.Schema({
"_id": { "type": String, "required": true },
"seq": { "type": Number, "default": 0 }
});