accessing json data array to store in mongodb, sub documenting - node.js

UserSchema
const UserSchema = new Schema({
name:{
type:String,
validate: {
validator: (name) => name.length>2,
message:'Name must be longer than 2 characters'
},
},
postCount:{
type:Number,
default:0
},
posts:
type:[PostSchema],
});
PostSchema
const PostSchema = new Schema({
title:{
type:String,
required:true
}
});
Post method to insert data into user document(mongodb)
app.post('/user',(req,res)=>{
console.log(req.body.posts);
var user = new User({
name:req.body.name,
posts: req.body.posts
});
user.save().then((doc)=>{
res.status(200).send(doc);
},(e)=>{
res.status(400).send(e);
});
});
Creating POST request using this JSON Data
{
"name":"TIM",
"posts":[
{"title":"abc", "name":"xxx"},
{"title":"xyz", "name":"xxx"}]
}
After requesting POST method on above JSON data
{
"postCount": 0,
"_id": "5c32301725d0c965bd5fa82e",
"name": "TIM",
"posts": [
{
"_id": "5c32301725d0c965bd5fa830"
},
{
"_id": "5c32301725d0c965bd5fa82f"
}
],
"__v": 0
}
I have created a userschema and sub-documented posts, now i am trying to insert data from postman using post method, but the title is not updating and only the id is generating for an indivisual posts. please help.
I should be able to add name of the user along side the array of posts and their titles.

Try
posts: [PostSchema]
Reference
https://mongoosejs.com/docs/subdocs.html
Also your post schema doesnt contain name field.
You are trying to insert a name via post.

Related

How can I delete referenced object id in mongodb in my node.js application?

I have been on this for days. I have tried so many things. I know I am not doing it rightly. I have a blog application I am building using node.js, mongodb and react.js. So, I have User Model, Post Model and Comment Model so far. I linked them up. What I did for post and comment models is this: When a user who made a comment deletes the comment, I want the referenced id of that comment in Post collection to be deleted as well from the database. It makes no sense if the comment referenced id remains in the database even though it has no content in it. It can be messy when you have many deleted comments. Comment Model is referenced in Post model. So, when a comment is deleted in Comment collection, the id referenced in the Post collection should be deleted as well. Look at my codes so far:
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',
},
postId:{
type: Schema.Types.ObjectId,
ref: "Post",
}
}, {timestamps: true}
);
CommentSchema.pre('update',function(next) {
this.model('Post').update(
{ },
{ "$pull": { "comments": this._id } },
{ "multi": true },
next
);
})
//exporting this schema
module.exports = mongoose.model("Comment", CommentSchema); //the module name is "Post"
I saw a post on this site about doing this with Mongodb middleware. I applied the middleware code inside my Comment Model as you can see above. It is not working. After deleting a comment, the referenced id in the Post collection is still there in the array. I am sure I am not doing it rightly.
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 deleting code
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 posts")
}
}catch(err){
console.log(err)
}
})
fetching post codes
//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",
}
})
This is a screenshot of the referenced id I am talking about. This particular comment has been deleted but the id is still found in that particular post array where the comment was made.
Your code would be somewhat like this:
deleteCommentById: async function (req, res) {
try {
if (req.params.type === "Comment") {
await postModel.updateMany({ postId: ObjectId(req.params.postId), type: 'Post' }, { $pull: { 'children': ObjectId(req.params.id) } });
await commentModel.updateMany({ postId: ObjectId(req.params.postId) }, { $pull: { 'comments': ObjectId(req.params.id) } });
}
await postModel.findByIdAndDelete(ObjectId(req.params.id));
return res.status(http_status.OK).json({ message: `${req.params.type} deleted successfully` });
} catch (error) {
return res.send("error");
}
}
SO, your code too will be somewhat like the code above which I have written as reference for you.
So instead of this :
CommentSchema.pre('update',function(next) {
Try to use .pre('remove') or .pre('delete') instead of update

How to update a document using update query in mongoose?

This is the comment key pair I have in my post model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const postSchema = new Schema({
user:{
type:Schema.Types.ObjectId,
// required:true,
refPath:'onModel'
},
onModel:{
type:String,
enum:['Doctor','Patient']
},
text:{
type:String,
required:true
},
comments:[{
user:{
type:Schema.Types.ObjectId,
refPath:'onModel'
},
reply:{
type:String
},
date:{
type:Date,
default:Date.now
}
}],
likes:[{
user: {
type: Schema.Types.ObjectId,
ref: 'Patient'
}
}]
})
module.exports= post = mongoose.model('post', postSchema);
When I try pushing object to the likes array by running the following code, it fails. The filter part works fine, just some problem with the update part which ends up executing catch block.
Post.updateOne({ _id: req.params.postid, "likes": { $ne : { user:
authorizedData.jwt_payload.patient._id }}},
{ "$set" : { "likes.$.user": "authorizedData.jwt_payload.patient._id"
}})
.then(re => res.json(re))
.catch(err => res.json("already liked"))
Will really appreciate any help.
Please make changes as below :
const mongoose = require('mongoose');
const patientObjectID = mongoose.Types.ObjectId(authorizedData.jwt_payload.patient._id);
Post.updateOne({
_id: req.params.postid,
'likes.user': {
$ne:
patientObjectID
}
},
{ $push: { likes: { user: patientObjectID } }
}).then(re => res.json(re)).catch(err => res.json("already liked"))
Couple of changes need to be done, So When you've a schema like this ::
likes: [{
user: {
type: Schema.Types.ObjectId,
ref: 'Patient'
}
}]
You need to pass an ObjectId() to user field but not a string, So
first we're converting string to ObjectId() & passing it in query.
Also $set is used to
update existing or insert new fields in a document, but when you wanted to push
new values to an array field in a document then you need to use
$push(this seems to be a normal update operation on a field, but here we're not replacing the likes array, rather we're just adding few more elements to it - different kind of update though, So that's why we need to use $push).
As you already have below filter, we're just doing $push assuming what we're pushing is not a duplicate but in the other way you can blindly use $addToSet to do the same without having to use below filter criteria :
"likes": {
$ne: {
user:
patientObjectID
}
}
About your question on $(update) why it isn't working ? This should be used to update the elements in an array, it helps to update first matching element in an array based on filter criteria, but what you wanted to do here is to add few more elements but not updating existing elements in likes array.
Here you should not send "already liked" in catch block, it should be a custom error for an actual error, in .then(re => res.json(re)) you need to check write result of update operation if anything updated you need to send added user, if not you need to send "already liked".
Hope this solves all your questions :-)
Try using $push aggregation which is used for pushing objects to inner arrays in mongoDB. Your update query should be something like the following:
Post.updateOne({ _id: req.params.postid, "likes": { $ne : { user:
authorizedData.jwt_payload.patient._id }}},
{ "$push" : { "likes": authorizedData.jwt_payload.patient._id
}})
.then(re => res.json(re))
.catch(err => res.json("already liked"))

How to fix mongoose query that returns empty array

I am trying to query for records in my database but I am getting an empty array. I don't know what I am doing wrong? I have a feeling the issue could be my schema, here it is:
my schema
const QuizSchema = new Schema({
question: {
type:String,
default:''
},
answers: [{
type: {
type: String,
default:''
},
content: {
type: String,
default:''
},
}]
});
module.exports=Quiz=mongoose.model('quizes',QuizSchema,'quiz');
Here is the mongoose query
const Quiz = require('../../models/Quiz');
router.get('/',(req,res)=>{
Quiz.find({},null)
.then(data=>res.json(data))
.catch(err=>console.log(err))
});
module.exports = router;
And here is a sample JSON data
{
"question": "What is a Mongoose ? ",
"answers": [
{ "type": "Smart","content": "Animal" }, {"type": "Subpar", "content": "Software"}, { "type": "Confused", "content": "Poem" }]
}
Would appreciate your assistance. Thanks in advance!
<query>.then doesn't return the data. You should use <query>.exec().then to access the data returned by the query. So change your code to something like:
Quiz.find({},null)
.exec()
.then(data=>res.json(data))
.catch(err=>console.log(err))
});
module.exports = router;
Source: Mongoose docs
Modify Schema like this: Inside the array, field name like 'type' is not accepted.
const QuizSchema = new Schema({
question: {
type:String,
default:''
},
answers: [{
ans_type: { // CHANGE HERE
type: String,
default:''
},
content: {
type: String,
default:''
},
}]
});
module.exports=Quiz=mongoose.model('quizes',QuizSchema,'quiz');

saving complex structure in mongodb using express and mongo

I'm new to mongodb, node and express. I I'm trying to save these data in mongodb.
I have staff.model.js as follows
let StaffSchema = new Schema({
staffcode:String,
firstname:String,
lastname: String,
type: String,
department:String,
dateofjoin:Date,
lastworkingday:Date,
teaching:[ {type:Schema.Types.ObjectId, ref:'Teaches'} ]
});
I have another schema named teaches as follows
let TeachesSchema = new Schema({
standard:{type: Schema.Types.ObjectId, ref: 'Standard'},
subjects:[{type: Schema.Types.ObjectId, ref: 'Subject'}]
});
another schema of standards as follows
let StandardSchema = new Schema({
name:String,
medium:String,
section:String
});
another schema subjects as follows
let SubjectSchema = new Schema({
name:{ type: String, required: true, max: 25 }
});
finally I'm trying to save data in mogodb as like
exports.staff_create = function(req, res){
let staff = new Staff({
staffcode:req.body.staffcode,
firstname:req.body.firstname,
lastname: req.body.lastname,
type: req.body.type,
department:req.body.department,
dateofjoin:req.body.dateofjoin,
teaching:req.body.teaching
});
staff.save(function(err){
if(err){
return next(err);
}
res.send('Staff created successfully');
});
};
making api call from postman with input like this
{
"staffcode": "STF0003",
"firstname": "Joh Doe",
"lastname": "Moy",
"type": "teaching",
"department": "physics",
"dateofjoin": "2018-06-01",
"teaching": {
"standard": {
"_id": "5cb8ff551a1c1a2514fa467c",
"name": "1",
"medium": "English",
"section": "A"
},
"subjects": [
{
"_id": "5cb8ed65c068b22f5489d050"
},
{
"_id": "5cb8ed6bc068b22f5489d051"
}
]
}
}
what is wrong in this? I'm not able to get success response in postman request.
your schema design is coming from relational databases. However you can do what you ask by using populate.
a better way would be to use embedded documents instead of referrals in some places check this answer about MongoDB relationships: embed or reference?

MongoDB vanishes attributes on save

Hi im using MongoDB + Mongoose and some strange magic happens in my app.
Ive defined my Schema as
var schema = mongoose.Schema({
username: {type: mongoose.Schema.ObjectId, ref: 'Profile' , required:true},
user: {type: mongoose.Schema.ObjectId, ref: 'Profile' , required:true},
message: String
});
As I save my Document the new entry has ben saved and stored. It has a message and a ref on Profile in username but the user field is missing.
Same happens if I rename it to userId :/ Registered a pre save listener : already missing in my callback before save
There is no Error and I do not know how to handle this situation. Please help. Would call the a team but I can not afford
Edit :
Full Schema
var mongoose = require('mongoose');
var schema = mongoose.Schema({
username: {type: mongoose.Schema.ObjectId, ref: 'Profile' , required:true},
user: {type: mongoose.Schema.ObjectId, ref: 'Profile' , required:true},
message: String
});
var autoPopulate = function(next) {
this.populate('user');
this.populate('username');
next();
};
var autoReduce = function(next) {
if(this.username){
this.username = this.username._id;
}
if(this.user){
this.user= this.user._id;
}
next();
};
schema.
pre('findOne', autoPopulate).
pre('find', autoPopulate).
pre('save', autoReduce);
module.exports = mongoose.model('News',schema);
Request Body
{
"message": "Hi",
"username": {
"_id": "5a736607bee0360014fb28e6",
"name": "Juventus Florin"
},
"user": {
"_id": "5a736607bee0360014fb28e6",
"name": "Juventus Florin"
}
}
Code
app.put("/api/news", function(request, response) {
response.header("Content-Type", "application/json");
var payload = request.body;
new News(payload).save(function(err) {
if(err){
response.status(500).send({"message": "This is an error!", "error":err, "payload":payload});
}else{
response.status(200).send(payload);
}
});
});
After saving there is an new entry , looks like (username is populated)
{
"message": "Hi",
"username": {
"_id": "5a736607bee0360014fb28e6",
"name": "Juventus Florin"
},
"_id":"5a736607bee0360014fb278h"
}
Solution :
On 1 to 1 references there is no need to
this.user = this.user._id;
Only on 1 to Many references. Removed the pre save listener autoReduce and it works

Resources