push items to an array in a object using Mongoose - node.js

I want to update the posts array in the data object.
It dosent work here is my schema:
const mongoose = require('mongoose');
const Post = require('./post');
const Review = require('./comment')
const User = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
username: {
type: String,
required: true
}
// necessary details needed for the user to initially working with
data: {
posts: [
Post
],
following: [String]
}
}
});
I have already tried:
User.update({_id: user}, {data:{$push: {posts: post
}}}).then(data=>{
console.log(data);
})
but it dosent work. Thank you.

Try this code:
User.update(
{ "_id": user },
{
"$push":
{
"data.posts": post
}
}
).then(data => {
console.log(data);
})
Read more about $push here.
Hope this solves your query!

Related

insert to MongoDB array with axios, restAPI and nodeJS

I am trying to add an item to a MongoDB array with RESTAPI through Axios. I thought it would look similar to the push method but I have no idea how to do that.
my Model is of a person:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: [],
missions: []
})
const personModel = mongoose.model('Person', PersonSchema);
I want to add a mission to the mission array of a person.
and for example, in order to add a new Person, I use NodeJS and API:
(api.js)
router.post('/api/people', (req, res) => {
const personToAdd = req.body;
const newPersonPost = new personModel(personToAdd);
newPersonPost.save((e) => {
if (e) {
console.log("error");
}
});
res.json({
msg: 'Received'
})
});
and in the client side I use Axios:
axios({
url: 'http://localhost:8080/api/people',
method: 'POST',
data: dataToUpdate
})
.then(() => {
console.log('axios sent info to server');
}).catch((e) => {
console.log('error' + e);
})
Thank you so much!
express
router.post('updating mission endpoint url', async (req, res) =>
try {
const query = { /* content */}; /* write a query to retrieve the concerned user by using a unique identifier */
let person = await personModel.findOne(query);
person.missions.push(req.body.mission);
personModel.save();
} catch (err) {
console.log(err);
}
});
client
In the client side you just have to put the mission you want to add in data like you did above with the right endpoint url and you should add a unique identifier for the user you want to add mission to.
[] will not assign array type to your variable.
Change your schema file with the following:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: { type: String },
password: { type: String },
friends: { type: Array },
missions: { type: Array }
})
Update the db model entity file with following
First method:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: {type : Array},
missions: {type : Array}
})
const personModel = mongoose.model('Person', PersonSchema);
Second Method :
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: [{ type: String }],
missions: [{ type: String }]
})
const personModel = mongoose.model('Person', PersonSchema);
You can update the array object as per your requirements.
You just want to be using the $push update operator, very simple, like so:
db.collection.updateOne(
{
_id: user._id
},
{
"$push": {
"missions": {
mission: newMission
}
}
})
Mongo Playground

Nodejs TypeError: Cannot read property 'push' of undefined

hey i am new here in nodejs and mongodb, i tyied to push comments on post in my social media project..
Here is my controller ,it shows error while pushing comments in mongodb
TypeError: Cannot read property 'push' of undefined
const Comment = require('../models/comment')
const Post = require('../models/post')
module.exports.create = function(req,res){
Post.findById(req.body.post, function(err ,post){
if(post){
Comment.create({
content: req.body.content,
post: req.body.post,
user: req.body._id
},function(err, comment){
if(err){console.log("error in pushing comment")}
post.comments.push(comment),
post.save()
res.redirect('/')
})
}
})
}
this is my comments schema
const mongoose = require('mongoose')
const commentSchema = new mongoose.Schema({
content: {
type: String,
required: true
},
//comments belongs to user
user : {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
post : {
type: mongoose.Schema.Types.ObjectId,
ref : 'Post'
}
},{
timestamps: true
})
const Comment = mongoose.model('Comment' , commentSchema)
module.exports = Comment
I recommend that you use Promises instead of callback functions. It will make your code way more readable. Monogoose findOneAndUpdate could be handy here.
As for the error, you should make a console.log(post.comments) to see the value for yourself.
We should see the model of Post. It should contain an array of Comments
const mongoose = require('mongoose')
const Comment = require('./comment.model.js') // Change the path
const postSchema = new mongoose.Schema({
// comments belongs to post
comments : {
type: [Comment]
},
// Other attributes here
},{
timestamps: true
})
const Post = mongoose.model('Post' , postSchema)
module.exports = Post
You'll end up with something like this:
const Comment = require('../models/comment')
const Post = require('../models/post')
module.exports.create = function (req, res) {
Post.findById(req.body.post).then((post) => {
if (post) {
Comment.create({
content: req.body.content,
post: req.body.post,
user: req.body._id
}).then((comment) => {
Post.findOneAndUpdate(
{ _id: req.body.post },
{ $push: { comments: comment } }
).then(() => {
res.redirect('/')
}).catch((error) => console.log(error))
})
}
}).catch((error) => console.log(error))
}

Filter collection on associated field ObjectId

SEE EDIT AT BOTTOM OF QUESTION.
I have a Node.js Express web application using MongoDB and Mongoose with collections for articles and comments. They have a one-to-many association where one article can have many comments.
The mongoose model schema is as follows:
// models/article
const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
title: { type: String },
content: { type: String },
}, {timestamps: true});
module.exports = mongoose.model('Article', articleSchema);
and
// models/comment.js
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
content: { type: String },
article: { type: mongoose.Schema.Types.ObjectId, ref: 'Article' },
}, {timestamps: true});
module.exports = mongoose.model('Comment', commentSchema);
I have a route with a parameter for the article id
// routes.js
router.get('/articles/:articleId/comments', commentsController.list);
And a controller with a callback function to query the database and return the comments with the given article id. It uses the mongoose find() method filtering on the article id taken from the route parameter.
// controllers/commentsController.js
exports.list = (req, res, next) => {
Comment.find({ article: req.params.articleId })
.exec((err, comments) => {
res.render('comments/list', { title: 'Comments', comments: comments });
});
};
But this turns up no results. Just experimenting I can see that the req.params.articleId is a string and any comment.article is an object so they match with a loose comparison == but not a strict comparison === unless I convert comment.article.toString(). Anyway, what is the proper way to do such a query. All my attempts have failed.
EDIT: I found the problem. The code above is as it should be. The issue must be related to how I seeded the DB which I did directly in MongoDB. I deleted all those records and just added them from the application and it works with the code above.
One way to approach this is to add the comments to your article model.
const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
title: { type: String },
content: { type: String },
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
]
}, {timestamps: true});
articleSchema.set('toJSON', {
transform: (document, returnedObject) => {
const article = returnedObject
article.id = article._id.toString()
delete article._id
}
})
module.exports = mongoose.model('Article', articleSchema);
Then get the comments in one of these ways:
const router = require('express').Router()
const Article = require('../models/article')
const Comment = require('../models/comment')
// article with comments
router.get('/:id', async (request, response, next) => {
try {
const article = await Article.findById(request.params.id)
.populate(
'comments', {
content: 1
}
)
response.json(article.toJSON())
} catch (err) {
console.log(err)
}
})
// list of comments belonging to an article
router.get('/:id/comments', async (request, response, next) => {
try {
const article = await Article.findById(request.params.id)
if (!article) {
response.status(404).json({ error: 'invalid request' })
}
const comments = await Comment.find({ article: request.params.id })
.populate(
'article', {
title: 1
}
)
response.json(comments.map(comment => comment.toJSON()))
} catch (err) {
console.log(err)
}
})
module.exports = router

Call a related collection via populate

I try to call a related list of logs for a certain user via Mongoose populate. Who can help me with finishing the response?
These are the schemes:
const logSchema = new Schema({
logTitle: String,
createdOn:
{ type: Date, 'default': Date.now },
postedBy: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'}
});
const userSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
logs: { type: mongoose.Schema.Types.ObjectId, ref: 'logs' }
});
mongoose.model('User', userSchema);
mongoose.model('logs', logSchema);
Inspired by the Mongoose documentary (see above) and other questions in relation to this subject I think I got pretty far in making a nice get. request for this user. I miss the expierence to 'translate it' to Express.
const userReadLogs = function (req, res) {
if (req.params && req.params.userid) {
User1
.findById(req.params.userid)
.populate('logs')
.exec((err, user) => {
if (!user) { }); // shortened
return;
} else if (err) {
return; // shortened
}
response = { //question
log: {
user: user.logs
}
};
res
.status(200)
.json(response);
});
} else { }); //
}
};
The response in Postman etc would be something like this:
{
"log": {5a57b2e6f633ce1148350e29: logTitle1,
6a57b2e6f633ce1148350e32: newsPaper44,
51757b2e6f633ce1148350e29: logTitle3
}
First off, logs will not be a list of logs; it will be an object. If you want multiple logs for each user, you will need to store is as an array: logs: [{ type: mongoose.Schema.Types.ObjectId, ref: 'logs' }]
From the Mongoose docs: "Populated paths are no longer set to their original _id , their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results." In other words, in your query user.logs will be the logs document for each user. It will contain all the properties, in your case logTitle, createdOn, and postedBy.
Sending user.logs as json from the server is as easy as: res.json(user.logs). So your query can look like this:
const userReadLogs = function (req, res) {
if (req.params && req.params.userid) {
User1
.findById(req.params.userid)
.populate('logs')
.exec((err, user) => {
if (!user) { }); // shortened
return;
} else if (err) {
return; // shortened
}
res.status(200).json(user.logs)
});
} else { }); //
}
};
I hope this makes it a little bit clearer!

How to do nested find in mongoose?

I have a user model which has todolists field, in the todolists field I want to get the specific todolist by id. my query is like this:
User.find({_id: user._id, _creator: user, todoList: todoList._id}, 'todoLists') // how do I query for todoList id here? I used _creator this on populate query.
Can I also do a search on a Usermodel field like this?
User.todoLists.find({todoList: todoList._id})
I haven't tested this yet because I am still modifying my Graphql schema and I am new in mongoose.I would really appreciate Links and suggestions. Help?
Assuming your models looks like this:
const todoListSchema = new Schema({
item: { type: String },
}, { collection: 'todolist' });
const userSchema = new Schema({
todoList: [todoListSchema],
}, { collection: 'user' });
mongoose.model('user', userSchema);
mongoose.model('todoList', todoListSchema);
Now you have multiple ways to do that:
1. Using the array filter() method
reference
User.findById(_id, (err, user) => {
const todoList = user.todoList.filter(id => id.equals(tdlId));
//your code..
})
2. Using mongoose id() method
reference
User.findById(_id, (err, user) => {
const todoList = user.todoList.id(tdlId);
//your code..
})
3. Using mongoose aggregate
reference
User.aggregate(
{ $match: { _id: userId} },
{ $unwind: '$todoList' },
{ $match: { todoList: tdlId } },
{ $project: { todoList: 1 } }
).then((user, err) => {
//your code..
}
});

Resources