Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$inc a default non 0 value with findOneAndUpdate and upsert true #3617

Closed
dciccale opened this issue Nov 25, 2015 · 9 comments
Closed

$inc a default non 0 value with findOneAndUpdate and upsert true #3617

dciccale opened this issue Nov 25, 2015 · 9 comments

Comments

@dciccale
Copy link
Contributor

hi, i am having trouble starting a counter n at a specified number and then increasing by 1 using findOneAndUpdate and upsert: true.

var RefSchema = new Schema({
  _id: {type: String, default: 'refs'},
  n: {type: Number, default: 776}
});

...

var query = {_id: 'refs'};
var update = {$inc: {n: 1}};
var options = {upsert: true, 'new': true};
// this will create the doc if it doesn't exist the first time, 
// it should use the default value from the schema instead of the value passed to $inc
RefSchema.findOneAndUpdate(query, update, options, function (err, doc) {
  console.log(doc.n); // is 1 but i expect to see 776
});

what i expect is the creation of a document with the n property starting at 776 and then increasing from that value.

@dciccale dciccale changed the title $inc a default non 0 value $inc a default non 0 value with findOneAndUpdate and upsert true Nov 26, 2015
@vkarpov15
Copy link
Collaborator

Use the setDefaultsOnInsert option. Or just manually use {$inc: {n:1}, $setOnInsert: {n:776} }.

@dciccale
Copy link
Contributor Author

using $setOnInsert doesn't seem to work, I get undefined instead of a document

  var RefSchema = new Schema({
    _id: {type: String, default: 'refs'},
    n: {type: Number, default: 776}
  });

  ...

  var query = {_id: 'refs'};
  var update = {$inc: {n: 1}, $setOnInsert: {n: 766}};
  var options = {upsert: true, 'new': true};
  RefSchema.findOneAndUpdate(query, update, options, function (err, doc) {
    console.log(doc); // is undefined
  });

if I use setDefaultsOnInsert option

var options = {upsert: true, 'new': true, setDefaultsOnInsert: true};

It doesn't start at 766, but 1, same issue as before.

If I remove the $inc: {n: 1} part from the update, it actually starts at 766 but doesn't increase it so it doesn't help much

@dciccale
Copy link
Contributor Author

Oops, I'm using mongo 3.0.0 probably is a bit old :( will update and try again!, sorry & thx

@dciccale
Copy link
Contributor Author

mongoose 4.1.5, mongodb version shouldn't be an issue right?

EDIT: updated everything to latest, still not working.

any suggestions?

@vkarpov15
Copy link
Collaborator

No setDefaultsOnInsert should work fine against mongodb 3.0. I'll double check

@vkarpov15 vkarpov15 reopened this Nov 28, 2015
@dciccale
Copy link
Contributor Author

dciccale commented Feb 2, 2016

I think that is not allowed to use $inc with $setOnInsert because the record doesn't exist. if I use $setOnInsert alone it works, or $inc alone also.
But I wanted a query that every time is called, is either incrementing the value or if the first time the record wasn't there, create it with a default value.

Basically what I want to do is something like this (working example):

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var RefSchema = new Schema({
  _id: {type: String, default: 'refs'},
  ref: {type: Number, default: 776}
});

RefSchema.statics.increment = function (callback) {
  var query = {_id: 'refs'};
  var update = {$inc: {ref: 1}};
  var options = {upsert: true, 'new': true, setDefaultsOnInsert: true};

  this.findOneAndUpdate(query, update, options, callback);
};


var RefModel = mongoose.model('Ref', RefSchema);

var OrderSchema = new Schema({
  total: Number,
  ref: Number
});

OrderSchema.pre('save', function (next) {
  if (!this.isNew) {
    return next();
  }

  var self = this;
  RefModel.increment(function (err, doc) {
    self.ref = doc.ref;
    next(err);
  });
});

var OrderModel = mongoose.model('Order', OrderSchema);

var orders = [];

for (var i = 0; i < 100; i++) {
  orders.push({total: (i + 1) * 3.4});
}

OrderModel.create(orders, function (err, orders) {
  console.log('orders', orders);
});

So this is working but it is starting the ref count in 1. instead of 766. I just can't get it to start on other number other than 1.

Again, what it suspect is that with upsert, it will create the document with the value of the $inc instead of the specified in the default.

I am trying to find where is this happening.. will update asap if if i find something.

anything from your side?

@dciccale
Copy link
Contributor Author

dciccale commented Feb 2, 2016

I found this conversation https://groups.google.com/forum/#!topic/mongodb-user/A93n4zEXClk that relates to this ticket in mongodb https://jira.mongodb.org/browse/SERVER-6566

so far what i understand is that this could be achieved with an array of updates as it is proposed in the jira ticket.

@vkarpov15
Copy link
Collaborator

So if you specify $inc on a field, setDefaultsOnInsert will explicitly ignore it, because mongodb treats $inc and $setOnInsert on the same field as an error:

> db.test.updateOne({}, { $inc: { test: 1 }, $setOnInsert: { test: 50 } }, { upsert: true });
2016-02-02T16:24:59.148-0500 E QUERY    [thread1] uncaught exception: WriteError({
    "index" : 0,
    "code" : 16836,
    "errmsg" : "Cannot update 'test' and 'test' at the same time",
    "op" : {
        "q" : {

        },
        "u" : {
            "$inc" : {
                "test" : 1
            },
            "$setOnInsert" : {
                "test" : 50
            }
        },
        "multi" : false,
        "upsert" : true
    }
}) :
undefined

As such, there's no good way for mongoose to have sane handling for setDefaultsOnInsert if the defaults field is anywhere in the update operation until the mongodb server can handle this case better.

Also, I opened up a separate issue #3835 that's somewhat related to this one.

@ashfaqnisar
Copy link

@dciccale, I know this has been too long. But, were you able to find a solution for this thing ?

@Automattic Automattic locked and limited conversation to collaborators Apr 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants