Why mongoose doesn't update? - node.js

I am learning Node.js. I am stuck in this Mongoose section because of this problem.
findById(id) doesn't get my result back and update() doesn't work. I don't know why..
const mongoose = require("mongoose").set("debug", true);
mongoose
.connect("mongodb://localhost/exercise")
.then(() => console.log("Connected Successfully!"))
.catch(err => console.error("Error: ", err.message));
const courseSchema = new mongoose.Schema({
tags: [String],
date: { type: Date, default: Date.now() },
name: String,
author: String,
isPublished: Boolean,
price: Number
});
const Courses = mongoose.model("Course", courseSchema);
async function updateCourse(id) {
const course = await Courses.findById(id);
course.author = "Muhib";
const result = await course.save();
console.log(result);
}
updateCourse("5a68fde3f09ad7646ddec17e");
// console.log(Courses);
I get this error :
TypeError: Cannot set property 'author' of null
This is a snip of my record:
btw find() works..
Thanks in advance :)

I solved the issue..
there is nothing wrong with the code...
first thing first WHY IT DOESN'T WORK
This problem occurs with the imported collections only. Because the
imported collection contains _id property as a string
for example {"_id":"5a6900fff467be65019a9001","tags":["angular","frontend"],"date":"2018-01-24T21:56:15.353Z","name":"Angular Course","author":"Mosh","isPublished":true,"price":15,"__v":0}
but what mongoose need is _id wrapped in ObjectId
SOLUTION
when importing json object always make sure that _id is not a string but an object with a $oid as a key and _id as a value for example
{"_id":"5a6900fff467be65019a9001","tags":["angular","frontend"],"date":"2018-01-24T21:56:15.353Z","name":"Angular Course","author":"Mosh","isPublished":true,"price":15,"__v":0}
should be {"_id":{"$oid":"5c91a66d079f4807847fcde3"},"tags":["angular","frontend"],"date":"2018-01-24T21:56:15.353Z","name":"Angular Course","author":"Mosh","isPublished":true,"price":{"$numberInt":"15"},"__v":{"$numberInt":"0"}}

Try to add try/catch. I'm not sure course..save() work without err
async function updateCourse(id) {
try {
const course = await Courses.findById(id);
course.author = "Muhib";
const result = await course.save();
console.log(result);
} catch (err) {
console.log('err' + err);
}
}
Edit 1: I found a solution a this post
async function updateCourse(id) {
try {
const course = await Courses.findById(id).exec();//fixed at here
course.author = "Muhib";
const result = await course.save();
console.log(result);
} catch (err) {
console.log('err' + err);
}
}
Another solution using findOneAndUpdate
try {
var course = await Courses.findOneAndUpdate(
{"id" : id},
{$set: {"author" : "Muhib"}},
{new : true}
);
res.status(200).json(course);
} catch (error) {
console.log('err' + err);
}

Related

Nodejs exports returns undefined on mongoose Insertion

I have created nodejs application by organising as module structure , The problem I am facing is that a mongodb insertion return undefined value from one of my controller, The issue I found is that my async funtion doesn't wait to complete my mongodb operation But I could not find a solution for that, my route and controller code is given below
route.js
const {
createEvent, editEvent
} = require('./controller');
router.post("/event/create", validateEventManage, isRequestValidated, async(req, res) => {
let data = {};
data.body = req.body;
try{
let event = await createEvent(req.body);
console.log(event) // returned undefined
data.event = event;
res.status(200).json(data);
}catch(error){
console.log(error)
res.status(200).json({error:error});
}
});
controller.js
exports.createEvent = async(data) => {
// return "test" // This works correctly
const eventObj = {
name : data.name,
description : data.desc,
type : data.type,
startDate : new Date()
}
const event = await new Event(eventObj);
await event.save((error,event)=>{
if(error) {
return error;
}
if(event){
return event;
}
});
}
You should not await the new Event constructor.
Also, since you are using async - await you can
remove the callback from the save and try ... catch the error to handle it:
exports.createEvent = async (data) => {
// return "test" // This works correctly
const eventObj = {
name: data.name,
description: data.desc,
type: data.type,
startDate: new Date(),
};
try {
const event = new Event(eventObj);
await event.save();
return event;
} catch (error) {
return error;
}
};

model.save() not working using Mongoose and MongoDB Atlas

I am new to using MongoDB, and trying to save some data into MongoDB Atlas using Mongoose. I am possibly doing something blatantly wrong, but I do not understand why it is not working. I get no response from it, no error.
Here is the code:
File 1:
const SavedGuild = require('./models/guild.js');
module.exports = new class {
async get(id) {
return await SavedGuild.findById(id)
|| await new SavedGuild({ _id: id }).save();
}
}
(I have tried SavedGuild({ _id: id }).markModified("guild").save(), same result)
File 2 (./models/guild.js):
const { model } = require('mongoose');
class GeneralModule {
prefix = '/';
blacklistedChannelIds = [];
}
module.exports = model('guild', {
_id: String,
general: { type: Object, default: new GeneralModule() }
});
Mongoose is initiated with this code:
const mongoose = require('mongoose');
try {
mongoose.connect(
`${process.env.mongourl}`,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log("Mongoose is connected")
);
} catch (e) {
console.log("Mongoose could not connect");
}
All help appreciated!

How do I stop duplicates from being created in a Mongoose Array | NodeJS Mongoose

Okay soo how do i stop duplicates from being created in a Mongoose Array
Heres My Code:
channel.send(`Welcome ${member.user.tag} Invited By ${invite.inviter.tag}`)
client.invites[invite.code] = invite.uses
const req = await InviteLogger.findOne({
ServerID: member.guild.id,
UserID: invite.inviter.id
})
if(!req) {
const doc = new InviteLogger({
ServerID: member.guild.id,
UserID: invite.inviter.id
});
await doc.save();
};
const doc = await InviteLogger.findOneAndUpdate({ServerID: member.guild.id, UserID: invite.inviter.id},{ $inc: { Joins: 1 } }, {new: true});
if(req.Invited === member.user.id) {
return;
}
const doc1 = await InviteLogger.findOneAndUpdate({ServerID: member.guild.id, UserID: invite.inviter.id},{ $push: { Invited: member.user.id } }, {new: true});
Also Heres a Screenshot on how the Schema Looks:
If you don't want member.user.id to be duplicated, use the following:
if(member.user.id.includes(req.Invited)) return;
This checks if member.user.id is one of the elements in the array.
And remove this part of your code:
if(req.Invited === member.user.id) {
return;
}
This code does nothing as it checks if the entire array is equal to member.user.id, when all you want to do is check if it's part of the array.

I want to delete all the item but except of the current user

I am creating a call that deletes all the users except the current user logged in.
Here is my code;
exports.deletealluser = async (req, res) => {
try {
const { sub } = req.user;
const usersExceptCurrent = await User.find({ _id: !sub });
const deletedUsers = await User.deleteMany(usersExceptCurrent);
res.status(201).json({
message: 'A all user is successfully deleted!',
deletedUsers,
});
} catch (err) {
return res.status(400).json({
message: 'Something went wrong.',
});
}
};
sub is the id of the current user. As you can see, I call find query first to filter the data which is not equal to sub. Then I use the usersExceptCurrent as filter to my deleteMany query.
But it returns status 400
And here is my axios call;
const onDelete = async () => {
try {
const { data } = await fetchContext.authAxios.delete(
'admin/delete-all-users'
);
fetchContext.setUserList(
fetchContext.userList.filter((row) => row === data.deletedUsers)
);
setSignupSuccess(data.message);
setSignupError('');
setOpen(false);
setOpenAlert(false);
} catch (err) {
setIsLoaded(true);
setError(err);
const { data } = err.response;
setSignupError(data.message);
setSignupSuccess('');
}
};
Use $ne
$ne selects the documents where the value of the field is not equal to the specified value. This includes documents that do not contain the field.
db.collection.find({ _id: { $ne: sub } })
Demo - https://mongoplayground.net/p/ecMNn4ueZrn
If you still face for _id should be ObjectId you can do
const ObjectId = require("mongodb").ObjectId;
db.collection.find({ _id: { $ne: ObjectId(sub) } })
See what ! does, converts to bool value in JS
console.log(!"a");
console.log(!2);

How do I give "document does not exist" feedback to the user when using the Mongoose deleteOne function?

I'm using NodeJS, Commander, and Mongoose to create a simple CLI. If my delete function is called and it does not find a document in the database, I'd like it to say "Document does not exist." However, whenever I call the function, it always runs the else code and says document has been deleted. Even with 0 documents in the database. How do I give the proper feedback to the user?
const deleteNote = (label) => {
const search = new RegExp(label, 'i');
Note.deleteOne({'label': search,},
function(error, doc) {
if (error || !doc) {
console.log('Document does not exist');
mongoose.connection.close();
} else {
console.log(`Document deleted`);
mongoose.connection.close();
}});};
Use the second argument from callback.
const mongoose = require("mongoose")
const Schema = mongoose.Schema
mongoose.connect('mongodb://localhost/stackoverflow', {useNewUrlParser: true});
const NoteSchema = new Schema({
title: String,
label: String
})
const NoteModel = mongoose.model("Note", NoteSchema)
function run(label) {
NoteModel.deleteOne({ label }, (err,result)=>{
console.log(result) // { n: 0, ok: 1, deletedCount: 0 }
// deletedCount shows number of docs deleted
if(result.deletedCount > 0) {
console.log("DELETED")
} else {
console.log("NOT DELETED")
}
})
}
run("Label 2")

Resources