question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

bulkWrite UpdateOne fails handling sub-documents while the updateOne() and findOneAndUpdate() funcitons work

See original GitHub issue

Do you want to request a feature or report a bug? A Bug

What is the current behavior? The current behavior is bizzare. I have a model that has an array of schema that I have created. I am attempting to do a bulk update which runs without error, but doesn’t actually update anything. With the same filter and update ‘$set’ command, the update works when not using bulk write. updateOne() and findOneAndUpdate() both work.

If the current behavior is a bug, please provide the steps to reproduce. Here are the schema and models:

const mongoose = require('mongoose');
const SectionInfoSchema = require('./section-info');

const SubjectInfoSchema = mongoose.Schema({
  code: { type: String, requried: true, index: true },
  subjectTitle: { type: String, requried: true },
  courses: { type: [SectionInfoSchema], requried: true }
});

module.exports = mongoose.model('subject-info', SubjectInfoSchema);`

Here is the schema for SectionInfo:

const mongoose = require('mongoose');

const SectionInfoSchema = new mongoose.Schema({
  courseid: { type: String, required: true, index: true },
  crn: { type: String, required: true },
  profesorName: { type: String, required: true },
  subjectTitle: { type: String, required: true },
  sectionNumber: { type: String, required: true },
  seatsAvailable: { type: Number, required: true },
  creditHours: { type: Number, required: true },
  courseType: { type: String, required: true },
  meetingInfo: { type: Object, required: true }
});

module.exports = SectionInfoSchema;`

I run a script to webscrape some course info from my school (its public data). I then want to update this in my database with a bulk write. For reference coursesToBeUpdated is an array of objects that have a unique course id and the new data for the seats to be updated. Here is the code for setting up that bulkWrite:

var bulkOpsSection = [];     // Bulk operations for the section
var bulkOpsSubjectInfo = []; // Bulk operations for the subject infos
for(var i = 0; i < coursesToBeUpdated.length; i++) {

  // Section update doc
  let updateDoc = {
    'updateOne': {
      'filter': { 'courseid': coursesToBeUpdated[i].id },
      'update': { '$set': { 'seatsAvailable': coursesToBeUpdated[i].seatsAvailable } }
    }
  };

  // Subject Info update doc
  let thatOtherUpdateDoc = {
    'updateOne': {
      'filter': {'courses.courseid': coursesToBeUpdated[i].id},
      'update': { '$set':
        {
          'courses.$.seatsAvailable': coursesToBeUpdated[i].seatsAvailable
        }
      }
    }
  };

  // push the docs to the update queus
  bulkOpsSection.push(updateDoc);
  bulkOpsSubjectInfo.push(thatOtherUpdateDoc);
};

// update the section info
await Section.collection.bulkWrite(bulkOpsSection)
  .then( bulkWriteOpResult => {
    console.log('BULK update OK');
    console.log(JSON.stringify(bulkWriteOpResult, null, 2));
  })
  .catch( err => {
    console.log('BULK update error');
    console.log(JSON.stringify(err, null, 2));
  });

  
// update the subjectInfo
await SubjectInfo.collection.bulkWrite(bulkOpsSubjectInfo)
  .then( bulkWriteOpResult => {
    console.log('BULK update OK');
    console.log(JSON.stringify(bulkWriteOpResult, null, 2));
  })
  .catch( err => {
    console.log('BULK update error');
    console.log(JSON.stringify(err, null, 2));
  });

The bulkwrite on the section collection works fine. However, when adding the update operator ‘$’, the issue starts occurring where no error happens but nothing is updated. That same filter and update object works in the updateOne() function and findOneAndUpdate() function just not in this bulkWrite form.

What is the expected behavior? The expected behavior is to update each collection with the new and updated amount of seats available for the course. updateOne as it is seen being used as added to the list of docs for the bulkWrite should go through, find the document with that courseid, then use that found index to update the seats. It is not doing this.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that “latest” is not a version. Node.js: 12.18.3 Mongoose: 5.13.2 MongoDB:

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
IslandRhythmscommented, Sep 7, 2021

reportee claims no error but I am getting the error block to execute when I run this example.

const mongoose = require('mongoose');

const SectionInfoSchema = new mongoose.Schema({
    courseid: { type: String, required: true, index: true },
    crn: { type: String, required: true },
    profesorName: { type: String, required: true },
    subjectTitle: { type: String, required: true },
    sectionNumber: { type: String, required: true },
    seatsAvailable: { type: Number, required: true },
    creditHours: { type: Number, required: true },
    courseType: { type: String, required: true },
    meetingInfo: { type: Object, required: true }
  });


  const SubjectInfoSchema = mongoose.Schema({
    code: { type: String, requried: true, index: true },
    subjectTitle: { type: String, requried: true },
    courses: { type: [SectionInfoSchema], requried: true }
  });
  
  const Section = mongoose.model('Section', SectionInfoSchema);
  const SubjectInfo = mongoose.model('Subject', SubjectInfoSchema)

  async function test() {

    await mongoose.connect('mongodb://localhost:27017/test', {
        useNewUrlParser: true,
        useUnifiedTopology: true,
      });
      await mongoose.connection.dropDatabase();
      const coursesToBeUpdated = await SubjectInfo.create({ code: '12345', subjectTitle: 'Math', courses: [{courseid: '123', crn: '12', profesorName: 'Testerson', subjectTitle: 'Calculus', sectionNumber: '123456789', seatsAvailable: 10, creditHours: 3, courseType: 'Engineer', meetingInfo: {time: 'today'}}]});
    var bulkOpsSection = [];     // Bulk operations for the section
    var bulkOpsSubjectInfo = []; // Bulk operations for the subject infos
    for(var i = 0; i < coursesToBeUpdated.length; i++) {
    
      // Section update doc
      let updateDoc = {
        'updateOne': {
          'filter': { 'courseid': coursesToBeUpdated[i].id },
          'update': { '$set': { 'seatsAvailable': coursesToBeUpdated[i].seatsAvailable } }
        }
      };
    
      // Subject Info update doc
      let thatOtherUpdateDoc = {
        'updateOne': {
          'filter': {'courses.courseid': coursesToBeUpdated[i].id},
          'update': { '$set':
            {
              'courses.$.seatsAvailable': coursesToBeUpdated[i].seatsAvailable
            }
          }
        }
      };
    
      // push the docs to the update queus
      bulkOpsSection.push(updateDoc);
      bulkOpsSubjectInfo.push(thatOtherUpdateDoc);
    };
    
    // update the section info
    await Section.collection.bulkWrite(bulkOpsSection)
      .then( bulkWriteOpResult => {
        console.log('BULK update OK');
        console.log(JSON.stringify(bulkWriteOpResult, null, 2));
      })
      .catch( err => {
        console.log('BULK update error');
        console.log(JSON.stringify(err, null, 2));
      });
    
      
    // update the subjectInfo
    await SubjectInfo.collection.bulkWrite(bulkOpsSubjectInfo)
      .then( bulkWriteOpResult => {
        console.log('BULK update OK');
        console.log(JSON.stringify(bulkWriteOpResult, null, 2));
      })
      .catch( err => {
        console.log('BULK update error');
        console.log(JSON.stringify(err, null, 2));
      });
  }

  test();

Quick side note: the error object in this version of mongoose returns {“driver”:true, “name”:“MongoError”} but in 6.X its an empty object

Read more comments on GitHub >

github_iconTop Results From Across the Web

$push and $set same sub-document in an Array
bulkWrite() and issue the $set and $push on the "same path" in two separate operations. They need to be separate but what "bulk"...
Read more >
db.collection.updateOne() — MongoDB Manual
When true , updateOne() either: Creates a new document if no documents match the filter . For more details see upsert behavior.
Read more >
Doing bulkWrite using updateOne with upsert and ... - GitHub
When doing bulkWrite on model using updateOne with the options upsert and setDefaultsOnInsert set to true the inserted documents gets the ...
Read more >
Mongoose v6.8.2: API docs
path «String» The path a.b.c in the doc where this cast error occurred ... [options] «Object» passed down to the MongoDB driver's connect()...
Read more >
backend/node_modules/mongoose/History.md - Git01Lab
fix(schema): handle merging schemas from separate Mongoose module instances ... fix(query): throw handy error when using updateOne() with ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found