Mongo addPayment, if exists x,y,z exists then add x amount more

Hello,

I’m trying to have a collection of salaries with userId, month and year being the primary keys.
I want it to work with the following set of rules:

  1. If collection entry with userId - 1, month - 7, year - 2017, amount - 20 exists and I try to add the same entry again, it finds previously mentioned entry and just sums up the amount.
  2. If collection entry with mentioned primary keys does not exists then it creates it.

This is what I currently have

addPayment: function(userId, userFirst, userLast, month, year, amount){
if(!Meteor.userId()){
  throw new Meteor.Error('No access: You are not logged in.');
}


if (!Roles.userIsInRole(Meteor.userId(), 'admin')) {
userId = Meteor.userId();
}

var entryAdded = Salaries.findOne({"userId" : {$eq: userId}, "month": {$eq: month}, "year": {$eq: year}}, {fields: {amount:1}, limit: 1}).amount;
if(entryAdded != null && entryAdded > 0 && !entryAdded){
Salaries.update(userId, {$set: {amount: amount}});
} else {

Salaries.insert({
userId:userId,
createdAt: new Date(),
userFirst: userFirst,
userLast: userLast,
month: month,
year: year,
amount:amount
});
}

},

Currently getting ‘amount’ property is undefenied.

Doing a find, followed by an insert or update runs the risk of a race condition. The simplest way to handle this is to use upsert. Ensure you index the userId, month and year fields (I think you’ve already done this). A compound key will give greatest performance here.

Salaries.upsert({userId, month, year}, {$inc: {amount}});

If the _id for that query ({userId, month, year}) doesn’t exist, it and those fields will be inserted. If the amount field doesn’t exist it will be created, otherwise it will be modified.

Final note: I used ES6 property shorthand (e.g. {year} == {year: year}).

1 Like

Upsert works like a charm. Many thanks!

1 Like