1

I am trying to update a collection using async/await. Below is my code:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mongo-exercises')
    .then(() => {
        console.log('Connected to MongoDB');
        UpdateCourse("5a68fdd7bee8ea64649c2777");
    })
    .catch(error => console.error('Could not connect to MongoDB : ' + error));

    const courseSchema = mongoose.Schema({
        name: String,
        author: String,
        tags: [String],
        date: Date,
        isPublished: Boolean,
        price: Number
    });

const Course = mongoose.model('course', courseSchema);
async function UpdateCourse(id) {
    console.log(`Inside Update Course. Finding ${id}`);
    const course = await Course.findById(id);
    console.log(`Course: ${course}`);
    if(!course)
        return;
    
    course.isPublished = true;
    course.author = 'Another Author';
    //course.set({isPublished: true, author: 'Another Author'});
    const saved = await course.save();    
    console.log(saved);
}

I query the collection in mongo shell which produces the below output:

enter image description here In the UpdateCourse() method I am getting null as value for course. I do have the id in the collection. Could anybody tell me why I am getting this error while using async/await.

I tried changing findById() -> findOne({_id: id}). Same error. I tried changing findById() -> find({_id: id}) here I am getting UnhandledPromiseRejectionWarning: Unhandled promise rejection.. Not understanding why.

enter image description here

Abhilash D K
  • 1,223
  • 1
  • 23
  • 39
  • Wrap your code in `try/catch` so you can see the actual error. See https://javascript.info/async-await#error-handling. – zero298 Sep 10 '18 at 18:18
  • I did. With findById() and findOne() same problem course is set to Null. But with find I get `TypeError: course.save is not a function` error. – Abhilash D K Sep 10 '18 at 18:21
  • With `find` you get the error because it returns an array. Why are you so sure that you have the id in the collection? – Josh Sep 10 '18 at 18:35
  • If course is null you don't experience any error. `try/catch` won't help you – Josh Sep 10 '18 at 18:36
  • @Josh I have updated my question showing the document being available in the collection. Can you explain how to find a document by it's id in node.js. I have seen some examples. Even the call back pattern rather than async/await also produces null. – Abhilash D K Sep 10 '18 at 18:39
  • All I can think of is that maybe you aren't using the mongo-exercises db in the shell – Josh Sep 10 '18 at 18:40
  • did you save the document using mongoose or using the mongo shell? – Josh Sep 10 '18 at 18:41
  • @Josh. I have updated my question which shows the db too. I imported the document using mongodb import command. I did not use mongoose to save the document. – Abhilash D K Sep 10 '18 at 18:43
  • @Josh the mongoose version I am using is `"mongoose": "^5.0.12"`. Let me update it and try. – Abhilash D K Sep 10 '18 at 18:50
  • No, the version is okay. Anyway, if it doesn't work with callbacks either, the version shouldn't be the problem – Josh Sep 10 '18 at 18:53
  • I updated to new mongoose version 5.2.14 and in both versions I am able to get a list of courses using `async function GetCourses() { return courses = await Course .find(); }`. But still the above code return null :(. My node version is `v10.5.0`. Is that a problem? – Abhilash D K Sep 10 '18 at 18:55
  • And the list of courses includes the id you use? No, that's no problem. – Josh Sep 10 '18 at 19:00
  • @Josh yes it includes the _id I use. Actually I am copying the id from the mongo shell and then using it in the code. So no typing mistake or misplaced characters. – Abhilash D K Sep 10 '18 at 19:01

1 Answers1

2

The _id value in the document you're trying to find is a String, not an ObjectId. So you need to update your schema to define _id as a String; otherwise Mongoose will cast any _id values in your queries to the default _id type of ObjectId (resulting in the query not matching the document).

const courseSchema = mongoose.Schema({
    _id: String,
    name: String,
    author: String,
    tags: [String],
    date: Date,
    isPublished: Boolean,
    price: Number
});

Having said all that, you probably want to update your documents to use ObjectId values for _id instead of String, as it's more efficient.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
  • after adding `_id: String` I am able to retrive the object. Thank you. One Question though. When I imported the documents these _id's were create automatically I did not explicitly create them so they should be ObjectId's rather than Strings, am I correct? - Sorry the .json file contains the _id field as a string. – Abhilash D K Sep 10 '18 at 19:06
  • Right, best practice would be to use ObjectIds instead of Strings. – JohnnyHK Sep 10 '18 at 19:08
  • Sorry I just opened the .json file and I see that the _id is String. Thanks for the explanation. @Josh thanks for your help. – Abhilash D K Sep 10 '18 at 19:10