MongooseJS: Having a hard time populating a list of comments - javascript

I have a schema called Post, and in the Schema, there is a comments attribute.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const PostSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: "users",
},
text: {
type: String,
required: true,
},
name: {
type: String,
},
avatar: {
type: String,
},
likes: [
{
user: {
type: Schema.Types.ObjectId,
ref: "users",
},
},
],
comments: [
{
type: Schema.Types.ObjectId,
ref: "comments",
},
],
date: {
type: Date,
default: Date.now,
},
});
module.exports = Post = mongoose.model("post", PostSchema);
Here is my Comments schema.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const CommentSchema = new Schema({
post: {
type: Schema.Types.ObjectId,
ref: "posts",
},
user: {
type: Schema.Types.ObjectId,
ref: "users",
},
text: {
type: String,
required: true,
},
name: {
type: String,
},
avatar: {
type: String,
},
likes: [
{
user: {
type: Schema.Types.ObjectId,
ref: "users",
},
},
],
replies: [
{
type: Schema.Types.ObjectId,
ref: "comments",
},
],
date: {
type: Date,
default: Date.now,
},
});
module.exports = Comment = mongoose.model("comment", CommentSchema);
When I print out the data accessed by a post, I get it like below:
{
"_id": "630a82d564540e7196fe4887",
"user": "6301a168783647db9f7a37c8",
"text": "For the police I say ____ you punk, reading my rights and ____ it's all junk",
"name": "e",
"avatar": "//www.gravatar.com/avatar/8fd046f9f8f50ab2903fa9fd6c845134?s=200&r=pg&d=mm",
"comments": [
"630aa7c425ae8add2b275b53",
"630a834959110e8e3305b471",
"630a83200cd98eb07fb5f543"
],
"likes": [],
"date": "2022-08-27T20:47:17.888Z",
"__v": 3
}
I have tried to populate the comments shown below but I'm getting an error:
router.post(
"/commentOnPost/",
[auth, check("text", "Text is required").not().isEmpty()],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const user = await User.findById(req.user.id);
const post = await Post.findById(req.body.post_id).populate('comments');
let newComment = Comment({
post: post.id,
text: req.body.text,
name: user.name,
avatar: user.avatar,
user: req.user.id,
});
await newComment.save();
post.comments.unshift(newComment);
await post.save();
return res.json(await post);
} catch (err) {
errorLog(err);
res.status(500).send("Server error");
}
}
);
Sat Aug 27 2022 19:27:22 GMT-0400 (Eastern Daylight Time), -> MissingSchemaError: Schema hasn't been registered for model "comments".
Use mongoose.model(name, schema)

In your Comment schema, you named model as "comment". But in the Post schema, you referenced it as "comments".
Change your code in Post schema like this:
comments: [{ type: Schema.Types.ObjectId, ref: "comment" }],

Related

MongoDB: how can I pull an entire object from an object array that matches the Objectid?

My question is, how I can pull a team object in teams that matches the unique _id of a team(in teams array).
Here is what I have tried, however, the problem is that all entries in teams get deleted, instead of only the object that matches the team _id.
router.put("/delete/team/:id/:org", (req, res) => {
const orgid = req.params.org;
const _id = req.params.id;
Organization.findOneAndUpdate(
{
_id: orgid,
},
{
$pull: {
teams: { _id: _id },
},
},
{ multi: true }
)
.then((organization) => {
res.status(200).json(organization);
})
.catch((err) => {
res.status(400).json(err);
});
});
Each Organization in OrganizationSchema has a unique _id.
Also, each team(object) in teams array has a unique _id.
const OrganizationSchema = new Schema({
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
register_date: {
type: Date,
default: Date.now,
},
teams: [
{
sport: {
type: String,
required: false,
},
access_code: {
type: Number,
required: false,
},
admin: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
events: [
{
date_time: {
type: Date,
offset: true,
},
opponent: {
type: String,
required: true,
},
home_away: {
type: String,
required: true,
},
expected_attendance: {
type: Number,
},
people_attending: [
{ type: mongoose.Schema.Types.ObjectId, ref: "User" },
],
amenities: [String],
},
],
},
],
});
The probable reason for the output you are getting is, because you are matching an ObjectId with a string.
You need to convert your string to an object.
You can do this by adding,
const ObjectID = require('mongodb').ObjectID
And then,
$pull: {
teams: { _id: new ObjectID(_id) },
},

Mongoose Population issue

I'm trying to populate the records schema with users, So i can account for a user for each record. However, i am only getting a blank array back.
Here are my schemas:
1.The Records schema:
const mongoose = require('mongoose')
const RecordsSchema = new mongoose.Schema({
Title: {
type: String,
required: true
},
users: [{
type: [mongoose.Schema.Types.ObjectId],
ref: 'users'
}],
Author: {
type: String,
required: true
},
ISBN: {
type: String,
required: true
},
Review: {
type: String
},
SelectedFile: {
type: String
},
Likes: {
type: Number,
default: 0
},
Date: {
type: Date,
default: Date.now()
}
});
module.exports = Records = mongoose.model('records', RecordsSchema ');
Here is the The user Schema:
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
username: {
type: String
},
email: {
type: String,
required: true,
unique: true
},
records: [{
type: [mongoose.Schema.Types.ObjectId],
ref: 'records'
}],
password: {
type: String,
required: true
},
Date: {
type: Date,
default: Date.now,
immutable: true
}
});
module.exports = User = mongoose.model('users', userSchema);
The express route:
router.get('/all', async (req, res) => {
try {
const records = await Records.find()
.sort({ Date: -1})
.populate('users')
.exec()
res.json(records);
} catch (err) {
console.error(err.message);
res.status(404).send('Server Error');
}
});
Result:
{
"users": [],
"Likes": 0,
"_id": "5fed8c12a4fb2c1e98ef09f6",
"Title": "New Age",
"Author": "Situma Prisco",
"ISBN": "23422",
"SelectedFile": "",
"Review": "",
"Date": "2020-12-31T08:30:10.321Z",
"__v": 0
}
I'm getting a blank Array After populating. What am I doing wrong?

I have a Schema with Sub Schema. I want to update particular data in the Sub Schema

this is my schema
const mongoose = require('mongoose')
const MaterialListSchema = new mongoose.Schema({
nomenclature:{
type: String,
required: true
},
national: {
type: String,
required: true
},
partnumber:{
type:String,
required:true
},
quantity: {
type: Number,
required: true
},
unit:{
type: String,
required: true
},
price: {
type: Number,
required: true
}
})
const MrrlSchema = new mongoose.Schema({
aircrafttype:{
type: String,
required: true
},
mrrlcategory:{
type: String,
required: true
},
materiallist: [MaterialListSchema]
})
const Mrrl = mongoose.model('Mrrl', MrrlSchema)
module.exports = Mrrl
this is my update code . but it will delete all the sub document on the selected and will only have remaining
Mrrl.updateOne({
'materiallist': {$elemMatch: { _id: req.params.id}}
},{
$set: { materiallist: req.body }
}).then((data)=>{
console.log(data)
})
If i understand your question, you need use arrayFilters
// it is your req.body
const newMaterial = {
nomenclature: '2'
};
const result = await MrrlSchema.updateMany({ 'materiallist': {$elemMatch: { _id: req.params.id }} },
{ "$set": { "materiallist.$[material]": newMaterial } },
{ "arrayFilters": [ { "material._id": req.params.id } ] });
Note: arrayFilters can be use only with 3.6+ mongo

How to add a new Object to a property of object in a model

let userSchema = new Schema({
email: {type: String, required: true},
password: {type: String, required: true},
name: {type: String, required: true},
phoneNumber: {type: Number, required: true},
schedule: {type: String, required: true},
courses: {type: Array, required: false}
});
I have this condition, my problem is how to add a new course to courses property but in my case course is an another object. I could update using updateOne method, but it changed 1 item but not another.
As I understand, you want to embed courses into the user model.
So you need to make this change in your user model:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
let userSchema = new Schema({
email: { type: String, required: true },
password: { type: String, required: true },
name: { type: String, required: true },
phoneNumber: { type: Number, required: true },
schedule: { type: String, required: true },
courses: [
new Schema({
name: String
})
]
});
module.exports = mongoose.model("User", userSchema);
And create a course for the given user like this:
app.post("/user/:id/course", async (req, res) => {
const result = await User.findByIdAndUpdate(
req.params.id,
{
$push: {
courses: {
name: req.body.name
}
}
},
{
new: true
}
);
res.send(result);
});
When you send a request to url http://localhost:3000/user/5de2cf9323f76c207c233729/course with this body:
(Note that 5de2cf9323f76c207c233729 is an existing user _id)
{
"name": "Course 1"
}
The response will be like this, meaning the course is added to the user:
{
"_id": "5de2cf9323f76c207c233729",
"email": "abc#def.net",
"password": "123123",
"name": "Max",
"phoneNumber": 123123123,
"schedule": "sc1",
"courses": [
{
"_id": "5de2cfa723f76c207c23372a",
"name": "Course 1"
}
],
"__v": 0
}

Why am I getting an empty array from MongoDB when querying using object properties?

I'm having this seemingly trivial but persistent issue when trying to retrieve documents from MongoDB. I'm using Mongoose as the ODM and have trouble fetching documents matching a specific condition. I've had a look at similar issues/questions but no suggestion seems to work for me.
Below is a snippet of an example involving fetching meetup objects that match a specific location's name.
export default {
Query: {
//...
meetupsByLocation: async (parent, { location }, { Meetup }, info) => {
try {
const meetups = await Meetup.find({
"location.name": { "$eq" : location, "$exists" : true }
});
// Tried this one too but to no avail
//const meetups = await Meetup.find({ "location.name": location });
return meetups.map(meetup => {
meetup._id = meetup._id.toString();
return meetup;
});
} catch (error) {
throw new Error(error.message);
}
}
//...
},
Mutations: {
//...
},
};
Meetup GraphQL Schema
export default `
scalar DateTime
type MeetupLocation {
name: String!
longitude: Float!
latitude: Float!
}
type MeetupDetails {
name: String!
hostedBy: String!
description: String!
imageUrl: String!
eventStart: DateTime!
eventEnd: DateTime!
}
type Meetup {
id: ID!
addedBy: String!
type: [String!]!
location: MeetupLocation!
details: MeetupDetails!
photos: [String]!
attendees: [String]!
comments: [String]!
}
# Queries
type Query {
meetupsByLocation(location: String!): [Meetup]!
}
`
Meetup Mongoose Schema
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const MeetupSchema = new Schema(
{
addedBy: { type: Schema.Types.ObjectId, ref: 'User' },
type: { type: [String] },
location: {
name: { type: String },
longitude: { type: Number },
latitude: { type: Number },
},
details: {
name: { type: String },
hostedBy: { type: Schema.Types.ObjectId, ref: 'User' },
description: { type: String },
imageUrl: { type: String },
eventStart: { type: Date },
eventEnd: { type: Date },
},
photos: { type: [String] },
attendees: [{ type: Schema.Types.ObjectId, ref: 'User' }],
comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
},
{
timestamps: true,
}
);
export default mongoose.model('Meetup', MeetupSchema);
NB: Edited to include schema.

Categories

Resources