Hello,
I would like each ‘insert’ in the collection ‘courses’ to be increased by 1.
Of course ‘inserts’ can be made from several posts simultaneously.
Can I be sure that this syntax guarantees the uniqueness of ‘crs_numero’?
In other words, does the ‘insert’ and the ‘find’ that it contains form an indivisible operation?
Courses.insert({
"crs_abo_id": "000456",
"crs_numero": "201703"+("000"+(Courses.find().count()+1)).substr(-3),
"crs_nombre": '1', .....
Thank you for your reply
YC
No - find
is an asynchronous method (even though Meteor hides that very well) and so interleaving is possible and multiple inserts could be given the same value for crs_numero
.
You should look at using findOneAndUpdate
to manage unique counters, which is available as a Promise from Courses.rawCollection().findOneAndUpdate()
. I use this to generate “auto-increment” numbers in MongoDB collections. I’ve got a similar example posted here using the now deprecated findAndModify
and wrapAsync
(also not needed anymore).
Check out this article for information in how to use async
and await
instead of wrapAsync
here:
“Hou la la” (In french in the text)
‘Find’ an assynchrone request is not too good news, even if I think it is for good reasons.
The solution with findOneAndUpdate seems very complicated
I prefer another way that suits me better, and that is to make a loop on the insert as long as I have the error ‘duplicate key’ on a unique index. Just two or three turns in the loop …
insertCourse =function(doc) {
while (1) {
var nb =Courses.find({'crs_abo_id':doc.crs_abo_id,'crs_mois':doc.crs_mois}).count()
doc.crs_numero =doc.crs_mois+("000"+(nb+1)).substr(-3)
try {
var results = Courses.insert(doc);
break
} catch (e) {
if(e.code==11000){
continue; // duplicate key
}else {
return "duplicateKey"
break;
}
}
}
}
Thank you for all the information you gave me.
YC