0

I've looking over various other similar questions and just can't seem to make sense of why I can't push an object of just 2 numbers to an array.

The examples I've tried copying from are these: Mongoose findOneAndUpdate: update an object in an array of objects How to push an array of objects into an array in mongoose with one call? Mongoose .find string parameters

And the official docs: https://mongoosejs.com/docs/api.html#mongoosearray_MongooseArray-push

This is my schema

const BatchSchema = new mongoose.Schema({

  title: {
    type: String,
    required: true,
    trim: true
  },

  envRecord: {
    type: [{
      tmp: {
        type: Number
      },
      hum: {
        type: Number
      }
    }],
  }

});

BatchSchema.plugin(timestamp);

const Batch = mongoose.model('Batch', BatchSchema);
module.exports = Batch;

My push code looks like this:

 server.put('/batches/:title', async(req, res, next) => {
    //Check for JSON
    if (!req.is('application/json')) {
      return next(new errors.InvalidContentError("Expects 'application/json'"));
    }

    try {
      const batch = await Batch.findOneAndUpdate(
        { _title: req.params.title },
        req.body,
        batch.envRecord.push({ tmp, hum })
      );
      res.send(200);
      next();
    } catch(err) {
      return next(new errors.ResourceNotFoundError(`There is no batch with the title of ${req.params.title}`));
    }
  });

Using post man I'm using PUT to send the following JSON in the body

http://xxx.xx.xx.xxx:3000/batches/titleGoesHere
{
    "tmp": 20,
    "hum": 75
}

What I'm kind of confused by is that all of the examples I've found are using $push but the official docs don't seem to have that anymore and instead are using MongooseArray.prototype.push() which is why I was trying to reference mine as batch.envRecord.push({ tmp, hum })

Yes I have checked if the title matches and the batch can be found with

server.get('/batches/:title', async(req, res, next) => {

    try {
      const batch = await Batch.findOne({title: req.params.title});
      res.send(batch);
      next();
    } catch(err) {
      return next(new errors.ResourceNotFoundError(`There is no batch with the title of ${req.params.title}`));
    }
  });
AustinFoss
  • 385
  • 5
  • 13

1 Answers1

0

You are passing batch.envRecord.push({ tmp, hum }) as a third argument of findOneAndUpdate which represents query options object. So you need to push the object only after findOneAndUpdate is executed and save it. The downside on this approach is that 2 queries are executed:

const batch = await Batch.findOneAndUpdate(
  { title: req.params.title },
  req.body   
).exec();

batch.envRecord.push({ tmp, hum });
batch.save();

That is why using $push is a preferred approach.

Volodymyr
  • 1,360
  • 1
  • 7
  • 12
  • so `$push` is not a something in mongoose and is part of something else? How would that look in this instance? I had tried that several times without success. Granted the examples were from 2014/15 so maybe the syntax has changed since? – AustinFoss Nov 06 '18 at 17:35