Alexander Weinrauch
Alexander Weinrauch

Reputation: 311

Increment or create object in sub-array

I want to store/update statistics for each year. I have the following model

{
  entityid: ObjectId,
  stats: [
    { year: 2018, value: 25 }
  ]
}

(This model is a bit simplified, in reality the year has also an array with months -> days -> hours. But the problem stays the same for the simplified model)

For updating I can simply use $inc like

db.statistics.updateOne(
  {entityid, 'stats.year': 2018},
  {$inc: { 'stats.$.year': 1}}
) 

But now a problem arises when a new year begins because there will be no { year: 2019, value: 0 } inside the stats array. Upsert can not really be used because of the positional operator $.

The current solution is to check the result of the update query above if we actually modified a document. If no changes were applied we execute a push to insert the array element for the new year and execute the update again.

The solution feels like a hack and produces some problem with race conditions where multiple objects are pushed for the same year, although this can be fixed easily.

Can the update/push operation be performed in one go? Or is there a better database model to store this information?

Upvotes: 1

Views: 147

Answers (1)

sushant mehta
sushant mehta

Reputation: 1284

You can either follow your hack or make database like this and use upsert on the year key while using $inc on value
    {
      entityid: ObjectId,
      year: 2018,
      value: 25
    }

and use $group on entityid while fetching data if you want to group data.

Upvotes: 1

Related Questions