Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Mongo 5 findOneAndUpdate aggregation pipeline for default counter value?

Theres a several old questions (2015/2016) about doing an upsert with $inc that has a default value. The consensus seemed to be do multiple DB calls. I’m hoping there is a more modern approach to this now. I’m using Mongo 5.0.9.

I found this example that states you can now use $cond in update aggregation pipelines. I tried the following:
https://stackoverflow.com/a/62819768/1795570

Trying to convert it to my problem I came up with:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const result = await context.params.tenantDb.collection('counters').findOneAndUpdate({
    // Filter
    name: options.name,
  }, {
    // Data
    $set: {
      value: {
        $cond: {
          if: {$eq:[{$type:"$value"} ,  "missing"]},
          then: 1000,   // it's the upsert case
          else: { // it's the update case
             $inc: {
               value: 1
             }
          }    
       }
      },
    },
  }, {
    // Mongo Options
    returnDocument: 'after',
    name: options.name,
    upsert: true,
  });

This however just adds the entire $cond as the value to my document.

 value: {
    _id: new ObjectId("62ab8829d8ea984d839e10f3"),
    name: 'my_counter',
    value: { '$cond': [Array] }
  },

Is it possible to do this?

>Solution :

You will be able to achieve that with this, you’re missing [] that will help you to use the aggregation framework, then you should have this

You will be able to achieve that with this, you ‘re missing [] that will help you to use the aggregation framework, then you should have this

const result = await context.params.tenantDb.collection('counters').findOneAndUpdate({
    // Filter
    name: options.name,
}, [{
    $set: {
        value: {
            $cond: {
                if: {
                    $eq: [{
                            $type: "$value"
                        },
                        "missing"
                    ]
                },
                then: 1000,
                // it's the upsert case
                else: {
                    $add: [
                        "$value",
                        1
                    ]
                }
            }
        },

    }
}], {
    // Mongo Options
    returnDocument: 'after',
    name: options.name,
    upsert: true,
    multi: true
});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading