Node.js with mongoose delete one array element - node.js

I am trying to delete one array element when I click delete button on jade view page.
When clicked, it's going to send selected instructor objected as req.body.
At sever side, it will find courses that contain the instructor objectId.
Any idea for me?
Thank you for reading it.
here is my code:
var id = req.body._id;
clist.find({ instructors: { $in: [id] } }).exec(function (err, result) {
result.forEach(function (obj) {
clist.update(
{ _id: new mongoose.Types.ObjectId(obj._id)},
{ $pull: { instructors : [new mongoose.Types.ObjectId(id)] } }
);
console.log(new mongoose.Types.ObjectId(obj._id) + ' was deleted');
});
});
Schema Clist and ilist:
var instructorlist = mongoose.Schema({
name: { type: String, required: true },
age: { type: Number, required: true },
gender: { type: String, required: true },
DOB: { type: Date, required: true, default: Date.now },
email: { type: String, required: true },
phone: { type: Number, required: true },
address: { type: String, required: true },
dateofstart: { type: Date, required: true},
courses: [{
type: mongoose.Schema.Types.ObjectId,
ref: "clist"
}]
});
var courselist = mongoose.Schema({
coursename: { type: String, required: true },
coursenumber: { type: String, required: true },
coursecredit: { type: Number, required: true },
courseroom: { type: String, required: false },
courseregisteddate: {type: Date, default: Date.now},
students: [{
type: mongoose.Schema.Types.ObjectId,
ref: "slist"
}],
instructors: [{
type: mongoose.Schema.Types.ObjectId,
ref: "ilist"
}]
});
one example for mongodb :
{
"_id": {
"$oid": "591a7a3b391a1842e8a69e23"
},
"coursename": "JDKD",
"coursenumber": "COMP4483",
"coursecredit": 4,
"courseroom": "sdaf",
"instructors": [
{
"$oid": "591a374422a3a13d38c0bbe5"
}
],
"students": [],
"courseregisteddate": {
"$date": "2017-05-16T04:04:11.848Z"
},
"__v": 0
}
When I add instructor objectID in Course.
var newcourse = new clist({
'coursename': req.body.coursename, 'coursenumber': req.body.coursenumber, 'coursecredit': req.body.coursecredit
, 'courseroom': req.body.room, 'instructors': instructors._id
});

Use same operation to find and update multiple
clist.update(
{ instructors: { $in: [id] }},
{ $pull: { instructors : { _id : new mongoose.Types.ObjectId(id) } } }, //or{ $pull: { instructors: mongoose.Types.ObjectId(id) } }
{
multi:true
},
function(error, success){
if(error){
console.log("error",error)
}
console.log("success",success)
});

Related

MongoDB geting an empty array from an aggregation

So I created this controller to get me the sum of all the orders totalPrice made by months
const getMonthlyOrderTotal = async (req, res) => {
try {
const year = req.params.year;
const aggregatePipeline = [
{
$match: {
createdAt: {
$gte: new Date(`${year}-01-01T00:00:00.000`),
$lt: new Date(`${year}-12-31T23:59:59.999`)
}
}
},
{
$group: {
_id: {
$month: "$createdAt"
},
total: {
$sum: "$totalPrice"
}
}
},
{
$sort: {
_id: 1
}
}
];
const orderTotals = await Order.aggregate(aggregatePipeline);
res.json(orderTotals);
} catch (err) {
res.status(500).json({ message: err.message });
}
};
this is the orderModel I am using
import mongoose from "mongoose";
const orderSchema = mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
client: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Client",
},
orderItems: [
{
name: { type: String, required: true },
qty: { type: Number, required: true },
image: { type: String },
price: { type: Number, required: true },
product: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Product",
},
},
],
totalPrice: {
type: Number,
required: true,
default: 0.0,
},
taxPrice: {
type: Number,
required: true,
default: 0.0,
},
isPaid: {
type: Boolean,
required: true,
default: false,
},
paidAt: {
type: Date,
},
isDelivered: {
type: Boolean,
required: true,
default: false,
},
deliveredAt: {
type: Date,
},
},
{
timestamps: true,
}
);
const Order = mongoose.model("Order", orderSchema);
export default Order;
and when I try to test this API in postman "http://localhost:5001/orders/orderstotal/2022" I always get an empty array even though there is stored data in mongoDB orders Collection

MongoD: How to update specific field of a document in a collection?

I have a collection of jobs in MongoDB and in this collection there is a field in the documents named as appliedUser. I want to update this field when a new user applies for this job.So basically this field stores the id's of all the users who are applying for this job.
I am using findOneAndUpdate() function but not able to do it.
Job.findOneAndUpdate({ _id: req.params.id }, { $set: { appliedUser:
req.user.id } }, function(err, job) {
console.log(job);
})
and here is my Schema:
const jobSchema = new Schema({
date: { type: Date, default: Date() },
expirydate: { type: Date, required: true },
name: { type: String, required: true },
companydetails: { type: String, required: true },
address: { type: String, required: true },
role: { type: String, required: true },
city: { type: String, required: true },
minsalary: { type: Number, required: true },
maxsalary: { type: Number, required: true },
skills: { type: Array, required: true },
minex: { type: Number, required: true },
appliedUser: [{ type: Schema.Types.ObjectId, ref: 'users', unique:
true }],
user: { type: String, required: true }
})
The array of the document is not updating. I am not able to find the errors.
Look like what you need is $addToSet. Example:
Job.findOneAndUpdate({ _id: req.params.id }, { $addToSet: { appliedUser: req.user.id } }, function(err, job) {
console.log(job);
})

$pull not removing element from collection

I am trying to make a like/unlike system. and for unlike i need to remove the user from array of likes. but the mongodb $pull doesn't work.
the $inc command works fine but $pull doesn't.
here is my schema
postedBy: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User"
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
],
likeCount: {
type: Number,
default: 0
},
commentBody: {
type: String
},
contentId: {
type: mongoose.Schema.Types.ObjectId,
refPath: "contentType",
required: true
},
contentType: {
type: String,
required: true,
enum: ["Video", "Comment"]
},
isApproved: {
type: Boolean,
default: true
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
],
postedOn: {
type: Date,
default: Date.now()
}
mongodb query
await Video.updateOne(
{ _id: contentId, likeCount: { $gt: 0 } },
{
$pull: {
likes: decoded.id
},
$inc: { likeCount: -1 }
}
);
You should update your query to look like this:
await Video.updateOne(
{ _id: contentId, likeCount: { $gt: 0 } },
{
$pull: {
"likes": { "_id": ObjectId(decoded.id)}
},
$inc: { likeCount: -1 }
}
);
I assume that in devede.id you have string, and string is not the same as ObjectId. Because of that we need to transform it to ObjectId.

How can I fetch data from more than one collections in Mongo using mongoose

How I can display details data of a profile when those data stored in more than one collections
tried this link
const profile = await userKushala
.find({_id: '5cd407c741f9e7373f10362c'})
.populate({
path: 'settingId',
populate : {
path : 'specialty',
populate : {
path: 'hospital_attached'
}
}
})
// First Collection(Basic Info.)
const userRegisterSchema = new Schema({
userType: {
type: String,
required: true
},
mobile: {
type: Number,
required: true,
unique: true
},
userId: {
type: String,
required: true
},
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
age: {
type: Number,
required: true
},
gender: {
type: String,
required: true
},
settingId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'providerSetting'
}
})
// Second Collection(Detailed Info.)
const serviceProfileUpdate = new Schema({
specialty :[{
type: mongoose.Schema.Types.ObjectId,
ref: 'specialtyMasterCsv'
}],
category: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'categoryMasterCsv'
}],
subscriptionPlan: {
type: mongoose.Schema.Types.ObjectId,
ref: 'planMasterCsv'
},
medicine: {
type : mongoose.Schema.Types.ObjectId,
ref: 'kushalaUser'
}
})
//Data in Mongo
{
"_id":{
"$oid":"5cd93ea6bd96e43664f49bf3"
},
"specialty":[
{
"$oid":"5cda85f26ffe60259a75ba17"
},
{
"$oid":"5cda85f26ffe60259a75ba18"
}
],
"category":[
{
"$oid":"5cda85f26ffe60259a75ba17"
},
{
"$oid":"5cda85f26ffe60259a75ba18"
}
],
"subscriptionPlan":{
"$oid":"5cda85f26ffe60259a75ba17"
},
"medicine":{
"$oid":"5cd407c741f9e7373f10362c"
},
"__v":{
"$numberInt":"0"
}
}
Expected Result will be from all the collections data should fetch but with the code I have it's giving the result till specialty but after that it's printing only ObjectID
This is what I have done and it's working still if anyone has a better solution, most welcome. Hope it helps someone.
const profile = await userKushala
.find({_id: '5cd407c741f9e7373f10362c'})
.populate({
path: 'settingId',
populate : {
path : 'specialty category subscriptionPlan medicine'
}
})
Try to populate like this:
.populate([
{path:'category',model:'categoryMasterCsv'},
{path:'subscriptionPlan',model:'planMasterCsv'},
{path:'medicine',model:'kushalaUser'}])
This is the method I use daily.

Mongoose sub field aggregation with full text search and project

I have a Mongoose model called Session with a field named course (Course model) and I want to perform full text search on sessions with full text search, also I wanna aggregate results using fields from course sub field and to select some fields like course, date, etc.
I tried the following:
Session.aggregate(
[
{
$match: { $text: { $search: 'web' } }
},
{ $unwind: '$course' },
{
$project: {
course: '$course',
date: '$date',
address: '$address',
available: '$available'
}
},
{
$group: {
_id: { title: '$course.title', category: '$course.courseCategory', language: '$course.language' }
}
}
],
function(err, result) {
if (err) {
console.error(err);
} else {
Session.deepPopulate(result, 'course course.trainer
course.courseCategory', function(err, sessions) {
res.json(sessions);
});
}
}
);
My models:
Session
schema = new mongoose.Schema(
{
date: {
type: Date,
required: true
},
course: {
type: mongoose.Schema.Types.ObjectId,
ref: 'course',
required: true
},
palnning: {
type: [Schedule]
},
attachments: {
type: [Attachment]
},
topics: {
type: [Topic]
},
trainer: {
type: mongoose.Schema.Types.ObjectId,
ref: 'trainer'
},
trainingCompany: {
type: mongoose.Schema.Types.ObjectId,
ref: 'training-company'
},
address: {
type: Address
},
quizzes: {
type: [mongoose.Schema.Types.ObjectId],
ref: 'quiz'
},
path: {
type: String
},
limitPlaces: {
type: Number
},
status: {
type: String
},
available: {
type: Boolean,
default: true
},
createdAt: {
type: Date,
default: new Date()
},
updatedAt: {
type: Date
}
},
{
versionKey: false
}
);
Course
let schema = new mongoose.Schema(
{
title: {
type: String,
required: true
},
description: {
type: String
},
shortDescription: {
type: String
},
duration: {
type: Duration
},
slug: {
type: String
},
slugs: {
type: [String]
},
program: {
content: {
type: String
},
file: {
type: String
}
},
audience: [String],
requirements: [String],
language: {
type: String,
enum: languages
},
price: {
type: Number
},
sections: [Section],
attachments: {
type: [Attachment]
},
tags: [String],
courseCategory: {
type: mongoose.Schema.Types.ObjectId,
ref: 'course-category',
required: true
},
trainer: {
type: mongoose.Schema.Types.ObjectId,
ref: 'trainer'
},
trainingCompany: {
type: mongoose.Schema.Types.ObjectId,
ref: 'training-company'
},
status: {
type: String,
default: 'draft',
enum: courseStatus
},
path: {
type: String
},
cover: {
type: String,
required: true
},
duration: {
type: Number,
min: 1
},
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date
}
},
{ versionKey: false }
);
I am not sure if what I tried is gonna bring me what I want and I am getting this error concerning the $unwind operator:
MongoError: exception: Value at end of $unwind field path '$course'
must be an Array, but is a OID
Any kind of help will be really appreciated.
You can try below aggregation.
You are missing $lookup required to pull course document by joining on course object id from session document to id in the course document.
$project stage to keep the desired fields in the output.
Session.aggregate([
{
"$match": {
"$text": {
"$search": "web"
}
}
},
{
"$lookup": {
"from": "courses",
"localField": "course",
"foreignField": "_id",
"as": "course"
}
},
{
"$project": {
"course": 1,
"date": 1,
"address": 1,
"available": 1
}
}
])
Course is an array with one course document. You can use the $arrayElemAt to project the document.
"course": {"$arrayElemAt":["$course", 0]}

Resources