Mongoose callback does not execute - node.js

I am trying to execute a callback after calling .findByIdAndDelete. Which actually does delete my item in the mongodb database, but the callback does not execute.
I've tried several solutions from other posts, but to no avail. How can I fix this?
Here's my code:
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const BoardSchema = new Schema({
name: String,
date: {
type: Date,
default: Date.now
}
}, { collection: 'boards' });
module.exports = Board = mongoose.model('board', BoardSchema);
Method Call
router.delete('/delete-board', (req, res) => {
console.log(req.body); // This does print out
var id = req.body.id;
Board.findByIdAndDelete(id, (err, board) => {
if (err) throw err;
console.log('stupid'); // This doesn't print out
return res.send({
message: 'Board has been deleted',
board: board
});
});
})

Check if req.body,id is valid id of any element in your database. If it isn't valid, your program won't execute callback, because it'll be not able to delete any element.

Related

How to get MongoDB _id of an inserted document

I want to create a document in my MongoDB database and take the _id of the new document.
This is what I'm doing:
const mongoose = require("mongoose");
const billingSchema = require("./models/billing");
const { ObjectId } = require("bson");
const { MongoClient } = require("mongodb");
const mongouri = "***";
var connection = mongoose.createConnection(mongouri);
var Bills = connection.model("Fatturazione", billingSchema, "Fatturazione");
exports.createBill = (b) => {
return new Promise((resolve, reject) => {
Bills.Create(b, function (err) {
if (err) {
reject(err);
} else {
console.log(mongoose.Types.ObjectId(b._id));
resolve();
}
});
});
};
and this is my Schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
//schema define the structure of the document
const billingSchema = new Schema({
data_fatturazione: {
type: Date,
required: true,
},
data_saldo: {
type: Date,
required: false,
},
totale: {
type: Number,
required: false,
},
pagato: {
type: Boolean,
required: false,
},
});
module.exports = billingSchema;
In the console.log() I want to print the _id of the last inserted document but it prints a non-existing id (it doesn't correspond to the _id of the last created document in the database). I also tried without using mongoose.Types.ObjectId() but it prints undefined. I don't understand where is the problem.
I call the function createBill() in another js file, passing an object with the correct fields.
You are trying to get the _id of argument b, which is passed to your createBill, which is logically undefined. Instead you must get the _id from a result of Bill.create, mongoose callbacks take 2 arguments as #Joe mentioned in the comments, so your code must look like this:
exports.createBill = (b) => {
return new Promise((resolve, reject) => {
Bills.Create(b, function (err, result) {
if (err) {
reject(err);
} else {
console.log(result._id);
resolve(result);
}
});
});
};

How to join 2 collections in mongoose using nodejs

I want to join two collection using mongoose nodejs but i am stuck,
collection1
collection2
const mongoose = require('mongoose');
const gameSchema = new mongoose.Schema({
providerName:{
type: String
},
gamesSettings :[{
type: mongoose.Schema.Types.ObjectId,
ref: 'games_setting'
}]
});
module.exports = mongoose.model('gamesDetails', gameSchema);
This is the route :
router.get('/', async (req, res)=>{
try {
const gamesDetails1 = await joinCollection.find();
res.json(gamesDetails1);
//res.render('./games/gamesetting', { data: gamesDetails1 });
} catch (e) {
res.json({ message: e });
}
});
I am getting null in response.
I'm not sure that I understood your question correctly but I'm thinking that what you need is to execute a query where you get gameeSetting populated. The answer to that would be:
const details = await gamesDetails.find().populate('gamesSettings');

Await returning undefined into the async function (var all_courses is undefined)

I am trying to return the courses that belong to a certain program. for that I use the async / await but it is not returning the courses of the program that happened as id in the asynchronous function:
Program Controller
function getProgram(req, res){
var programId = req.params.id;
Program.findById({'_id': programId}, (err, program)=>{
if (err) return res.status(500).send({message: 'Petition failed'});
if (!program) return res.status(404).send({message: 'There is not program to show'});
getCoursesByProgram(programId).then((value) =>{
return res.status(200).send({
program,
all_courses: value.all_courses
});
});
});
}
async function getCoursesByProgram(program_id){
var all_courses = await Course.find({'program': program_id}).exec((err, courses)=>{
if(err) return handleError(err);
return courses;
});
return{
all_courses: all_courses
}
}
Models
'use strict'
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CourseSchema = Schema({
title: String,
video: String,
creator: {type: Schema.ObjectId, ref: 'User'},
program: {type: Schema.ObjectId, ref: 'Program'},
description: String,
created_at: String
});
module.exports = mongoose.model('Course', CourseSchema);
'use strict'
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProgramSchema = Schema({
title: String,
creator: {type: Schema.ObjectId, ref: 'User'},
image: String,
description: String,
created_at: String
});
module.exports = mongoose.model('Program', ProgramSchema);
Please somebody can help me with that?
When you pass a callback to .exec, it no longer returns a promise. Instead, you can do error / value handling using promises:
try {
return { all_courses: await Course.find({'program': program_id}).exec() };
} catch (err) {
return handleError(err);
}
Note that getCoursesByProgram will always resolve unless handleError throws an error.
getProgram can also be an async function. You can consolidate the error handling too, although if you want more generalized error handling you will have to either catch the errors independently or parse the error messages somehow.
async function getProgram(req, res) {
try {
const programId = req.params.id;
const program = await Program.findById({'_id': programId}).exec();
if (!program) return res.status(404).send(...);
const courses = await getCoursesByProgram(programId);
return res.status(200).send({
program,
all_courses: value.all_courses,
});
} catch (err) {
res.status(500).send({ message: 'Petition failed' });
}
}

Cascade Delete in mongo

I am new to MongoDB. I created 4 collections & they are connected with each other. (I am using node.js to write it)
Here, it's my question. How can I delete all records at once? Is there something like deep level population?
This one holds all models.
const DataModel = mongoose.Schema({
_id: { type: mongoose.Schema.Types.ObjectId, ref: 'User', require: true},
order: { type: mongoose.Schema.Types.ObjectId, ref: 'Order', require: true},
});
User model
const userSchema = mongoose.Schema({//other stuff});
Order model
const orderSchema = mongoose.Schema({
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
//other stuff
});
Product model
const productSchema = mongoose.Schema({//other stuff});
I can delete the entry with these code from the database, but the other entries still there
exports.delete_data = (req, res, next) => {
const id = req.params.userId;
userDataModel.deleteOne({_id: id})
.exec()
.then(docs => {
res.status(200).json({
message: 'Record Deleted',
request: {
type: 'POST'
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
};
Update: However, I wonder, Could I call other defined delete functions for order, product inside delete_data
As #Geert-Jan suggest, cascade delete is my solution. The link that geert-jan gave solve my problem. However, I wonder, Could I call other defined delete functions for order, product inside delete_data
i did this and it could be good for someone who wants to delete documents in cascade linked to any field of a model.
async blackHole() {
try {
const rtn = new ApiResponse<any>();
const userId = id;
const accountId = mongoose.Types.ObjectId(id);
var CollectionNames: any[] = [];
mongoose.connection.db.listCollections().toArray(function (err, collections) {
CollectionNames = collections.map(c => c.name);
CollectionNames.forEach((element: any) => {
mongoose.connection.db.collection(element).deleteMany({ "account": accountId });
});
});
const accountController = new AccountController(this.wsParams);
await accountController.delete(id)
await super.delete(userId);
return rtn;
} catch (error: any) {
const rtn = new ApiResponse<any>();
rtn.message = error;
rtn.success = false;
rtn.status = 422;
return rtn;
}
}
I hope you can use it :D

Execute a model operation inside a different model hook using mongoose

I want to trigger a remove operation to a ModelB inside a mongoose pre.save hook from a ModelA.
Basically any time any ModelA is updated, I need to drop the ModelB collection:
This is what I tried, I don't get errors but the operations never ends:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = Schema.Types.ObjectId;
const permissionSetSchema = require('./permission-set');
const PermissionSet = mongoose.model('PermissionSet', permissionSetSchema);
const roleSchema = new Schema({
name : { type: String, required: true, unique: true, maxLength: 140 },
description: { type: String, maxLength: 300 },
});
roleSchema.post('update', (next, done) => {
PermissionSet.remove({}, err => {
if (err) { next(err); }
next();
});
});
The first arg is the document. The second is the next callback.
Should be:
roleSchema.post('update', (doc, next) => {
PermissionSet.remove({}, err => {
if (err) { next(err); }
next();
});
});
http://mongoosejs.com/docs/middleware.html

Resources