I read many similar posts,mostly examples are with callbacks. I am trying to create a comment and add it to my Post.
const Post = require('./models/Post');
const Comment = require('./models/Comment');
const newLocal = 'mongodb://localhost/postdb';
mongoose.connect(newLocal, {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => console.log('Successfully connect to MongoDB.'))
.catch((err) => console.error('Connection error', err));
async function readP() {
try {
const comment = await Comment.create(
{title : 'Boa tarde',
body: 'Adriana bonita',
postedBy : mongoose.Types.ObjectId("5f96e440f47c1d211e84d712")
});
const post = await Post.findOne({ title: 'BJohnson'}).
populate( {path : 'comment'},
);
} catch (err) {
console.log(err);
}
}
readP();
PostSchema
const PostSchema = new mongoose.Schema({
title: String,
body: String,
createdAt: {
type: Date,
default: Date.now,
},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
comments: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
}]
});
BJohnson post
{ "_id" : ObjectId("5fa13e1523e71045227bf74d"), "comments" : [ ObjectId("5fa13e1523e71045227bf74c") ]
Comment was created but it was not added to Post. How to specify path in a proper manner?
You can use findOneAndUpdate(). In your case it will find the Post and update the Post with commentId.
I'm assuming your Post Schema looks somewhat similar to this -
const mongoose = require('mongoose')
const PostSchema = new mongoose.Schema({
title: String,
body: String,
createdAt: {
type: Date,
default: Date.now,
},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
comments: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
}]
});
module.exports = PostSchema
const Post = require('./models/Post');
const Comment = require('./models/Comment');
const newLocal = 'mongodb://localhost/postdb';
mongoose.connect(newLocal, {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => console.log('Successfully connect to MongoDB.'))
.catch((err) => console.error('Connection error', err));
async function readP() {
try {
const comment = await Comment.create(
{title : 'Boa tarde',
body: 'Adriana bonita',
postedBy : mongoose.Types.ObjectId("5f96e440f47c1d211e84d712")
});
const post = await Post.findOne({ title: 'BJohnson'})
const commentIds = post.comments || [] // get all the comment Id's of the post
commentIds.push(comment.id) // Push the new comment id to existing comment Id's
const updatedPost = await Post.findOneAndUpdate({ title: 'BJohnson'}, {comments: commentIds}).populate({path : 'comment'});
} catch (err) {
console.log(err);
}
}
readP();
Related
I am trying to fetch the blogs that a user has posted using mongoose populate method but not able to do so but when I try to look for the user who posted a blog I am able to do so. Tell me what I am doing wrong.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
blogPosts: [{ type: mongoose.Types.ObjectId, ref: "Blogs", required: true }],
});
const Users = mongoose.model("Users", userSchema);
module.exports = Users;
This is my user model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const blogSchema = new Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
image: {
type: String,
required: true,
},
user: {
type: mongoose.Types.ObjectId,
ref: "Users",
required: true,
},
});
const blogs = mongoose.model("Blogs", blogSchema);
module.exports = { blogs, blogSchema };
this is my blogs model
router.get("/users/:id", async (req, res) => {
let userBlogs;
try {
userBlogs = await users.find({ _id: req.params.id }).populate("blogPosts");
if (!userBlogs) {
return res.status(404).json({ msg: "No user found" });
}
return res.status(200).json(userBlogs);
} catch (err) {
return res.status(500).json({ err });
}
});
this is the route that I use for fetching all the blogs that a user has posted.This is just sending me back an empty posts array.
router.post("/newBlog/:id", async (req, res) => {
let blogAuthor;
try {
blogAuthor = await users.findOne({ _id: req.params.id });
} catch (err) {
return res.status(404).json({ message: "user not found" });
}
const newBlog = blogs({
title: req.body.title,
description: req.body.description,
image: req.body.imageUrl,
user: blogAuthor._id,
});
try {
await blogAuthor.blogPosts.push(newBlog);
await newBlog.save();
return res.status(200).json(blogAuthor.blogPosts);
} catch (err) {
return res.status(500).json(err);
}
});
the above is the route that I use to add new blog to the db.
router.get("/allBlogs", async (req, res) => {
let allBlogs;
try {
allBlogs = await blogs.find({}).populate("user");
} catch (err) {
return res.status(404).json(err);
}
res.status(200).json(allBlogs);
});
this is the route that sends all the blogs posted by all the users.
Interesting thing is that when I try to populate the user of a blogpost that is working exactly as expected it is populating the user of the blog from the users model however when I try to do the reverse that's not working. It is not populating all the blogs that a user has posted.
router.post("/list/:shortId/recomment/:p_shortId", async (req, res, next) => {
const { shortId, p_shortId } = req.params;
const { comment } = req.body;
const email = req.tokenInfo.email;
try {
const authData = await User.findOne({email});
const postData = await Post.findOne({shortId});
const parentData = await Upment.findOne({p_shortId});
const newcomment = await Downment.create({
postType: 3,
author: authData,
post_id: postData,
parentment_id: parentData,
comment: comment
});
await Upment.updateOne({p_shortId}, {"$push": {"comments": newcomment._id}});
res.status(200).json({
result: 'recomment success'
})
} catch (err) {
err.message = `${err.message}, market post recomment error.`;
next(err);
}
});
updateOne doesn't work so I changed it to update
router.post("/list/:shortId/comment", async (req, res, next) => {
const { shortId } = req.params;
const { comment } = req.body;
const email = req.tokenInfo.email;
try {
const authData = await User.findOne({email});
const postData = await Post.findOne({shortId});
const newcomment = await Upment.create({
postType: 3,
author: authData,
post_id: postData,
comment: comment
});
// console.log(commentData);
await Post.updateOne({shortId}, {"$push": {"comments": newcomment._id}});
res.status(200).json({
result: 'comment success'
})
} catch (err) {
err.message = `${err.message}, market post comment error.`;
next(err);
}
});
then it worked. So I tried it in mongoDB Compass. like below
db.upments.updateOne({shortId: "wEhPg-wFqS0_2935vuZEQ"}, {"$push": {"comments": new ObjectId("62f38170e3dccbfe7a9842b2")}})
And this worked...
Only in the code, updateOne worked properly why this thing happens? how should I fix it?
thank you for listening question!!
here are schemas ^^ if you need anything more, let me know~
import mongoose from "mongoose"
import shortId from "./type/shortId.js"
const UpmentSchema = new mongoose.Schema({
shortId,
comment: String,
// closet:1, OOTD:2, board:3
postType: {
type: Number,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
},
post_id: {
type : mongoose.Schema.Types.ObjectId,
ref: "Post",
required: true
},
comments: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Downment",
}]
}, {
timestamps: true
}
);
const DownmentSchema = new mongoose.Schema({
shortId,
comment: String,
// closet:1, OOTD:2, board:3
postType: {
type: Number,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
},
post_id: {
type : mongoose.Schema.Types.ObjectId,
ref: "Post",
required: true
},
parentment_id: {
type : mongoose.Schema.Types.ObjectId,
ref: "Upment",
required: true
},
}, {
timestamps: true
}
);
export const Upment = mongoose.model("Upment", UpmentSchema);
export const Downment = mongoose.model("Downment", DownmentSchema);
It was an error in update({p_shortId})
p_shortId is not in the upment model
await Post.updateOne({shortId}, {"$push": {"comments": newcomment._id}});
my mistake ^^...
I am having a little trouble getting my mongoose virtuals to show up from deep populated fields. Here is the code of the backend function that is not behaving as I'd like it to:
exports.get_user_feed = async (req, res, next) => {
const options = { sort: { date: -1 } };
const user = await User.find(
{ username: req.params.user },
"username posts avatar followers following"
)
.populate({
path: "posts",
options,
populate: [
{
path: "author",
},
{ path: "comments", populate: { path: "author" } },
],
})
.sort({ "posts.date": 1 });
res.json({ ...user });
};
And here is the comment schema:
const mongoose = require("mongoose");
const { DateTime } = require("luxon");
const Schema = mongoose.Schema;
const CommentSchema = new Schema({
targetPost: { type: Schema.Types.ObjectId, ref: "Post", required: true },
author: { type: Schema.Types.ObjectId, ref: "User", required: true },
date: { type: Date, required: true },
content: { type: String, maxlength: 400 },
comments: [{ type: Schema.Types.ObjectId, ref: "Comment" }],
stars: [{ type: Schema.Types.ObjectId, ref: "User" }],
});
// Virtual for post's URL
CommentSchema.virtual("url").get(function () {
return "/" + this.targetPost.url + this._id;
});
// Virtual for formatted date.
CommentSchema.virtual("formatted_date").get(function () {
return (
DateTime.fromJSDate(this.date).toLocaleString(DateTime.DATE_MED) +
" at " +
DateTime.fromJSDate(this.date).toLocaleString(DateTime.TIME_SIMPLE)
);
});
//Export model
module.exports = mongoose.model("Comment", CommentSchema);
My goal is to get the comments from each post to also include the formatted_date of the comment, but this virtual is not getting included in the response that is sent - all the regular properties are being sent but not the virtual. Any help here would be appreciated.
Add this code in your Commnet Schema file before module.exports.
CommentSchema.method('toJSON', function () {
const {
...object
} = this.toObject({ virtuals:true });
return object;
});
I have a Comment Model, User Model and Post model. In Post Model, there is a field called 'comment' and I referenced Comment model there. That way, every comment made on that post will be populated.
Now, if a user deletes any comment, that comments get deleted but the id referenced in the Post Model still remains. Though it is not active but it remains there. In a situation where you have many comments that get deleted, that Post collection with the Comment referenced field will look messy. Is there a way around this? I want once a comment is deleted, it should also delete anywhere it is referenced. Here are my codes:
Post Model
//creating the user models for the database
const mongoose = require("mongoose"); //import mongoose
const Schema = mongoose.Schema;
const PostSchema = new mongoose.Schema(
{
title:{
type: String,
required: true,
unique: true,
},
description:{
type: String,
required: true,
},
postPhoto:{
type: String,
required:false,
},
username:{
type: Schema.Types.ObjectId,
ref: 'User'
},
categories:{
type: Array,
},
comments: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
unique: true,
}]
}, {timestamps: true},
);
//exporting this schema
module.exports = mongoose.model("Post", PostSchema); //the module name is "Post"
Comment Model
const mongoose = require("mongoose"); //import mongoose to be used
const Schema = mongoose.Schema;
const CommentSchema = new mongoose.Schema(
{
commentdescription:{
type: String,
required: true,
},
author:{
type: Schema.Types.ObjectId,
ref: 'User',
},
}, {timestamps: true}
);
//exporting this schema
module.exports = mongoose.model("Comment", CommentSchema); //the module name is "Post"
Codes that delete a comment
//comment delete
router.delete("/posts/:id/comment/:id", async (req, res) =>{
try{
const comment = await Comment.findById(req.params.id)
if(comment.author == req.body.author){
try{
await comment.delete()
res.status(200).json("Comment has been deleted")
}catch(err){
console.log(err)
}
}
else{
res.status(401).json("you can only delete your comment")
}
}catch(err){
console.log(err)
}
})
codes that populates comment in Post
//Get Post
router.get("/:id", async(req, res)=>{
try{
const post = await Post.findById(req.params.id).populate('username').populate({
path: "comments",
populate: {
path: "author",
}
})
See the attached image. You can see that comment field in Post collection is still with a comment ref that has been deleted. The comment is deleted from the Comment Collection. But I will also like to delete all places it is referenced.
my main language is not English, so I apologize for that
Some things need to be corrected
Post Model
const mongoose = require("mongoose"); //import mongoose
const Schema = mongoose.Schema;
const PostSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
unique: true,
},
description: {
type: String,
required: true,
},
postPhoto: {
type: String,
required: false,
},
// Commented for testing
// username: {
// type: Schema.Types.ObjectId,
// ref: "User",
// },
categories: {
type: Array,
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment",
unique: true,
},
],
},
{ timestamps: true }
);
//exporting this schema
module.exports = mongoose.model("Post", PostSchema);
Comment Model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const CommentSchema = new mongoose.Schema(
{
commentdescription: {
type: String,
required: true,
},
// Commented for testing
// author: {
// type: Schema.Types.ObjectId,
// ref: "User",
// },
postId: {
type: Schema.Types.ObjectId,
ref: "Post",
},
},
{ timestamps: true }
);
module.exports = mongoose.model("Comment", CommentSchema);
index.js
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true }));
const port = 3000;
var mongoDB = "mongodb://127.0.0.1/my_database";
mongoose.connect(mongoDB);
const Post = require("./Model/Post");
const Comment = require("./Model/Comment");
// add post
app.post("/posts/add", async (req, res) => {
console.log(req.body);
const post = await Post.create(req.body);
res.status(200).json({
success: true,
data: post,
});
});
// add comment
app.post("/comment/add", async (req, res) => {
const comment = await Comment.create(req.body);
const post = await Post.findByIdAndUpdate(
{ _id: comment.postId },
{
$addToSet: { comments: comment._id },
}
);
res.status(200).json({
success: true,
data: comment,
});
});
// get all post
app.get("/posts", async (req, res) => {
const post = await Post.find({});
res.status(200).json({
post,
});
});
// delete comment
app.delete("/comment/:id", async (req, res) => {
const com = await Comment.findById(req.params.id);
console.log("postid", com.postId);
await Post.findByIdAndUpdate(
{ _id: com.postId },
{
$pull: { comments: com._id },
},
{ new: true }
);
await com.delete();
res.status(200).json({
success: true,
});
});
app.listen(port, () => {
console.log("server connect");
});
Models are not smart to understand your intention that because you
deleted the comment, they should be deleted from everywhere.
Computers are stupid, you have to explain to them face to face.
at C:\Users\Deepak\Desktop\mern-ecommerce\mern-back-end\src\controller\cart.js:75:44
I am getting this error in controllers while making a post request.
Here is my code:
Controllers (Cart.js)
exports.getCartItems = (req, res) => {
Cart.findOne({ user: req.user._id })
.populate("cartItems.product", " _id name price productPictures")
.exec((error, cart) => {
if (error) return res.status(400).json({ error });
if (cart) {
let cartItems = {};
cart.cartItems.forEach((item, index) => {
cartItems[item.product._id.toString()] = {
_id: item.product._id.toString(),
name: item.product.name,
img: item.product.productPictures[0].img,
price: item.product.price,
qty: item.quantity,
};
});
res.status(200).json({ cartItems });
}
});
};
Routes (Cart.js)
router.post('/user/getCartItems', requireSignin, userMiddleware, getCartItems);
Models (Cart.js)
const mongoose = require('mongoose');
const cartSchema = new mongoose.Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
cartItems: [
{
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Products', required: true },
quantity: { type: Number, default: 1 }
}
]
}, {timestamps: true});
module.exports = mongoose.model('Cart', cartSchema);