.populate() returning empty array? - node.js

I'm working on project and I am trying to get the users reviews to display on the page. However whenever I run my application it returns an empty array and I'm not sure why, I have no issue with the getReviews function as it returns everything correctly, but getUserReviews just returns an empty array with no error. I've tried multiple methods and just can't seem to get it
Review Model
const mongoose = require("mongoose");
const Review = mongoose.model(
"Review",
new mongoose.Schema({
movieId: String,
reviewId: String,
content: String,
sentimentScore: String,
author: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
],
reponseTo: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
]
})
);
module.exports = Review;
User Model
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
roles: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Role"
}
]
})
);
module.exports = User;
Review Routes
const express = require('express');
const router = express.Router();
const {authJwt} = require("../middlewares");
const Review = require("../models/review.model")
router.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
router.post("/addReview", [authJwt.verifyToken], (req, res) => {
const review = new Review(req.body)
review.save((err, review) => {
if(err) return res.json({success:false, err})
Review.find({'_id': review._id})
.populate('author')
.exec((err, result) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, result})
})
})
})
router.post("/getReviews", [authJwt.verifyToken], (req, res) => {
Review.find({"movieId": req.body.data})
// console.log("ID ", req.body.data)
.populate('author')
.exec((err, reviews) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, reviews})
})
})
router.post("/getUserReviews", [authJwt.verifyToken], (req, res) => {
Review.find({"userId": req.body.data})
.populate({
path: 'author.user',
model: 'Review'})
.exec((err, reviews) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, reviews})
})
})

You try to query Review collection with userId field, and Review collection does not have userId field in its model definition.
Maybe you wanted to query author array? In that case, try this:
router.post("/getUserReviews", [authJwt.verifyToken], (req, res) => {
Review.find({ author: req.body.data })
.populate('author')
.exec((err, reviews) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, reviews})
})
})

Related

Get timestamps of a newly created mongo document in mongoose (MERN)

I'm working on a twitter clone to learn MERN stack, here's a new tweet route
router.route('/new')
.post( (req, res) => {
const { errors, isValid } = validateTweet(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
let tweet = new Tweet({
content: req.body.content,
created_by: req.user.id
})
User.findById(req.user.id, (err, user) => {
if (err) return res.status(400).json(err)
user.tweets.push(tweet._id);
user.save();
});
tweet.save();
return res.status(201).json(tweet);
});
Which does not return timestamps for the tweet, how can i achieve this without querying the database for the tweet before returning it?
Here's the model just in case:
const tweetSchema = new Schema({
content: {
type: String,
required: true,
minlength: 1,
maxlength: 128,
trim: true
},
created_by: {
type: Schema.Types.ObjectId, ref: 'User',
required: true
}
}, {
timestamps: true
});
const Tweet = mongoose.model('Tweet', tweetSchema);
What i ended up doing was making the funcion async then returning the result of the fulfilled save(). Not sure if this is a good practice or not.
router.route('/new')
.post( async (req, res) => {
const { errors, isValid } = validateTweet(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
let tweet = new Tweet({
content: req.body.content,
created_by: req.user.id
})
User.findById(req.user.id, (err, user) => {
if (err) return res.status(400).json(err)
user.tweets.push(tweet._id);
user.save();
});
tweet = await tweet.save();
return res.status(201).json(tweet);
});

How to delete comment that is inside of Post schema?

I'm working on social network app where user can make post and comment. I'm trying to delete comment that is inside of a post. I work with MERN (mongoose, express, react, nodejs). I can successfully delete post, but don't know how to delete its comment.
This is my Mongo connection:
const db = config.get('mongoURI') mongoose.connect(db,{useNewUrlParser: true,useUnifiedTopology: true})
.then(() => console.log('Connected to MongoDB.'))
.catch(err => console.log('Fail to connect.', err))
this is Post Schema
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const PostSchema = new Schema({
userID: {
type: Schema.Types.ObjectId,
ref: 'user'
},
content: {
type: String,
required: true
},
registration_date: {
type: Date,
default: Date.now
},
likes: [
{
type: Schema.Types.ObjectId,
ref: "user"
}
],
comments: [
{
text: String,
userID: {
type: Schema.Types.ObjectId,
ref: 'user'
}
}
]
})
module.exports = User = mongoose.model('posts', PostSchema)
and here is where i tried to delete it:
router.delete("/comment/:postId/:commentId", auth, function (req, res) {
Post.findByIdAndUpdate(
(req.params.postId),
{ $pull: { comments: req.params.commentId } },
{ new: true }
)
.then(post => console.log(post)
.then(() => {
res.json({ success_delete: true })
})
.catch(() => res.json({ success_delete: false })))
});
Well, I think you are creating an app named DevConnector. So I wrote code for the same in the past.
router.delete('/comment/:id/:comment_id', auth, async (req, res) => {
try {
const post = await Post.findById(req.params.id);
// Pull out comment
const comment = post.comments.find(
comment => comment.id === req.params.comment_id
);
// Make sure comment exists
if (!comment) {
return res.status(404).json({ msg: 'Comment does not exist' });
}
// Check user
if (comment.user.toString() !== req.user.id) {
return res.status(401).json({ msg: 'User not authorized' });
}
// Get remove index
const removeIndex = post.comments
.map(comment => comment.user.toString())
.indexOf(req.user.id);
post.comments.splice(removeIndex, 1);
await post.save();
res.json(post.comments);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});

How can I populate an existing Mongo Document when creating another?

I am using mongoose and express to build an API for storing technology work tickets. I have a field in my Ticket model that references a User id and an array field in my User model that references all the Tickets (by ID) that are owned by that user.
When I create a new Ticket (using HTTP post method), I want my database to automatically add that ticket's id to the tickets field of its assigned user (like a SQL Join). However, I can't get it to work.
I've tried updating my user model inside the /tickets POST request in my router, but can't wrap my head around how to actually make it work.
Here is my code:
// Ticket Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Promise = require('bluebird');
const ObjectId = mongoose.Schema.Types.ObjectId;
const User = require('./user');
Promise.promisifyAll(mongoose);
const TicketSchema = new Schema({
open: {type: Date, required: true},
close: Date,
description: {type: String, required: true},
done: Boolean,
status: String,
repairType: {type: String, required: true},
ticketOwner: {type: ObjectId, ref: 'User', required: true}
});
const Ticket = mongoose.model('Ticket', TicketSchema, 'tickets');
module.exports = Ticket;
// User Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Promise = require('bluebird');
const ObjectId = mongoose.Schema.Types.ObjectId;
const Ticket = require('./ticket');
Promise.promisifyAll(mongoose);
const UserSchema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
email: {type: String, required: true},
tickets: [{type: ObjectId, ref: 'Ticket'}]
});
const User = mongoose.model('User', UserSchema, 'users');
module.exports = User;
// Tickets Route
const express = require('express');
const router = express.Router();
const Ticket = require('../models/ticket');
router.route('/')
// READ all tickets.
.get(function(req, res, next) {
Ticket.findAsync({})
.then(function(tickets) {
res.json(tickets);
})
.catch(next)
.error(console.error);
})
// CREATE new ticket.
.post(function(req, res, next) {
let ticket = new Ticket();
let prop;
for (prop in req.body) {
ticket[prop] = req.body[prop];
}
ticket.saveAsync()
.then(function(ticket) {
console.log('success');
res.json({'status': 'success', 'ticket': ticket});
})
.catch(function(e) {
console.log('fail');
res.json({'status': 'error', 'error': e});
})
.error(console.error);
});
router.route('/:id')
// READ a single Ticket by ID
.get(function(req, res, next) {
Ticket.findOne({_id: req.params.id}, {})
.populate('ticketOwner')
.exec(function (e, ticket) {
if (e) return console.error(e);
res.json(ticket);
})
})
// UPDATE a Ticket
.put(function(req, res, next) {
let ticket = {};
let prop;
for (prop in req.body) {
ticket[prop] = req.body[prop];
}
Ticket.updateAsync({_id: req.params.id}, ticket)
.then(function(updatedTicket) {
return res.json({'status': 'success', 'ticket': updatedTicket})
})
.catch(function(e) {
return res.status(400).json({'status': 'fail', 'error': e});
});
})
// DELETE a Ticket
.delete(function(req, res, next) {
Ticket.findByIdAndRemoveAsync(req.params.id)
.then(function(deletedTicket) {
res.json({'status': 'success', 'ticket': deletedTicket});
})
.catch(function(e) {
res.status(400).json({'status': 'fail', 'error': e})
});
});
module.exports = router;
// Users Route
const express = require('express');
const router = express.Router();
const User = require('../models/user');
router.route('/')
// READ all users.
.get(function(req, res, next) {
User.findAsync({})
.then(function(users) {
res.json(users);
})
.catch(next)
.error(console.error);
})
// CREATE new user.
.post(function(req, res, next) {
let user = new User();
let prop;
for (prop in req.body) {
user[prop] = req.body[prop];
}
user.saveAsync()
.then(function(user) {
console.log('success');
res.json({'status': 'success', 'user': user});
})
.catch(function(e) {
console.log('fail');
res.json({'status': 'error', 'error': e});
})
.error(console.error);
});
router.route('/:id')
// READ a single User by ID
.get(function(req, res, next) {
User.findOne({_id: req.params.id}, {})
.populate('tickets')
.exec(function (e, user) {
if (e) return console.error(e);
res.json(user);
})
})
// UPDATE a User
.put(function(req, res, next) {
let user = {};
let prop;
for (prop in req.body) {
user[prop] = req.body[prop];
}
User.updateAsync({_id: req.params.id}, user)
.then(function(updatedUser) {
return res.json({'status': 'success', 'user': updatedUser})
})
.catch(function(e) {
return res.status(400).json({'status': 'fail', 'error': e});
});
})
// DELETE a User
.delete(function(req, res, next) {
User.findByIdAndRemoveAsync(req.params.id)
.then(function(deletedUser) {
res.json({'status': 'success', 'user': deletedUser});
})
.catch(function(e) {
res.status(400).json({'status': 'fail', 'error': e})
});
});
module.exports = router;

How to make a record in mongodb refrence model

I working on Mongoose and Express project where by I have 3 models: User, Album and Purchase. The purchase model references the user and album. I am creating a POST endpoint where by I can make a purchase and then retrieve the data as well as the user and album relations which should be populated with their data, but I am stuck.
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
// TODO: Define Schema
name: {
type: String,
required: true
}
})
var User = mongoose.model('User', userSchema)
var albumSchema = mongoose.Schema({
// TODO: Define Schema
title: {
type: String,
required: true
},
performer: {
type: String,
required: true
},
cost: {
type: Number,
required: true
}
})
var Album = mongoose.model('Album', albumSchema);
var puchaseSchema = mongoose.Schema({
// TODO: Define Schema
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Album'
},
album: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
})
var Purchase = mongoose.model('Purchase', puchaseSchema);
app.use(bodyParser.json());
app.listen(3000);
// TODO: GET /albums
app.get('/albums', (req,res) => {
Album.find()
.then((response) => {
res.json({data: response})
})
.catch(err => {
res.json({error: err})
})
})
// TODO: GET /albums/:id
app.get('/albums/:id', (req,res) => {
Album.findById(req.params.id)
.then(response => {
res.json({data: response})
.catch(err => {
res.json({Error: err})
})
})
})
// TODO: POST /albums
app.post('/albums', (req,res) => {
const newPost = Album({
title: req.body.title,
performer: req.body.performer,
cost: req.body.cost
})
newPost.save(err => {
if(err)
res.json({error: err})
})
.then(data => {
res.json({data: data})
})
})
// TODO: PUT /albums/:id
app.put('/albums/:id', (req,res) => {
Album.findByIdAndUpdate(req.params.id, req.body, {new: true},
(err, album) =>{
if(err) return res.status(500).send(err)
return res.json({data: album})
})
})
// TODO: DELETE /albums/:id
app.delete('/albums/:id', (req,res) => {
const id = req.params.id
Album.findById(id)
.then(docs => {
docs.remove()
res.status(204)
.json({data:docs})
})
})
// TODO: POST /purchases
app.post('/purchases', (req,res) => {
})```
This might help you. Look into mongoose's populate method.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.findById(purchase.id).populate('user').populate('album').then((purchaseData) => {
return res.json({purchaseData});
}).catch(e => {
console.log(e);
});
}).catch(e => {
console.log(e);
});
})
Here's an alternative for populating after saving the document.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.populate(purchase, [{path: 'user'}, {path: 'album'}], (err, data) => {
if(err) {
return res.json(e);
}
return res.json(data);
});
}).catch(e => {
console.log(e);
});
}
)
As mentioned here: https://mongoosejs.com/docs/api.html#model_Model.populate

mongoose only insert id, createdAt and updated fields

I'm learning to use Node.js and MongoDB. I have a problem when I try to save data to the database.
Here's my code
const Test = require('../models/test');
const test = (req, res, next) => {
let url = "http://localhost:3000/article"
request(url, (req, (err, fields) => {
if (err) {
return res.status(400).json({
error: "error"
})
}
var objTest = JSON.parse(fields.body);
console.log(objTest.user)
let test = new Test(objTest)
console.log("ini",test)
test
.save()
.then(result => {
res.send(result)
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}))
}
here my Test Schema
const testSchema = new mongoose.Schema(
{
tittle: {
type: String,
index: true,
},
content: {
type: String,
},
postedBy: { type: mongoose.Schema.ObjectId, ref: 'Author' },
created: {
type: Date,
default: Date.now,
},
},
{
timestamps: true,
},
);
module.exports = mongoose.model('Test', testSchema, 'tests');
The response in Postman is only id, createdAt and updatedAt. Thank you.

Resources