Get the data inside request array inside of a schema - node.js

How can I create a route to get postedby data which is inside requests array. The request array is inside of a Post schema
const mongoose = require("mongoose")
const {ObjectId} = mongoose.Schema.Types
const postSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
jobtitle:{
type: String,
required: true
},
requests:[{
text: String,
postedby:{type: ObjectId, ref: "User"}
}],
postedby:{
type: ObjectId,
ref: "User"
}
})
mongoose.model("Post", postSchema)
I tried this but I was getting another postedby
router.get("/acceptedpost",requireLogin,(req,res)=>{
Post.find({postedby:req.user._id})
.populate("postedby","_id name")
.then(accpost => {
res.json({accpost})
})
.catch(err => {
console.log(err)
})
})

If you want to match the req.user._id against the requests array, you can simply do:
Post.find({"requests.postedby": req.user._id})
.populate("postedby", "requests.postedby")
.then(accpost => {
res.json({accpost})
})
.catch(err => {
console.log(err)
})

Related

My mongoose populate() function isnt working, I dont know why

I'm trying to populate the content key of my posts model with the contents of my content collection but it isnt working. The content collection is getting populated but the data isnt getting passed to posts collection's content key.
Schemas:
const postsSchema = new mongoose.Schema({
_id: {
type: String,
required: true
},
title: {
type: String,
required: true
},
content: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Content' }]
})
const contentSchema = new mongoose.Schema({
_id: {
type: String,
required: true
},
subHeading: String,
subHeadingContent: String,
image: {
data: Buffer,
contentTyle: String
}
})
const content = mongoose.model("Content", contentSchema)
const posts = mongoose.model("Posts", postsSchema)
Post request to populate the collections:
// Write a new post
app.post("/create", function (req, res) {
let Posts = {
title: req.body.newTitle,
subheading: req.body.newSubHeading,
subheadingcontent: req.body.newSubHeadingContent
}
postsArray = [];
postsArray.push(Posts)
console.log(postsArray);
postsArray.forEach((post) => {
content.create({
_id: uuidv4(),
subHeading: post.subheading,
subHeadingContent: post.subheadingcontent
})
posts.create({
_id: uuidv4(),
title: post.title,
})
posts.find().populate('content').exec((err, posts) => console.log("populated: ", posts))
})
res.redirect("/overview");
})
You do not need to have a postsArray & a for loop since your only trying to create a post from a single object.
Anyways, the reason it's not showing up is because you need to push the content object to your posts array.
First, you give a variable to the content.create,
then you push the variable to the array when you're creating the post
app.post("/create", function (req, res) {
let post = {
title: req.body.newTitle,
subheading: req.body.newSubHeading,
subheadingcontent: req.body.newSubHeadingContent
}
const postContent = content.create({
_id: uuidv4(),
subHeading: post.subheading,
subHeadingContent: post.subheadingcontent
})
posts.create({
_id: uuidv4(),
title: post.title,
{ $push: { content: postContent } }
})
posts.find().populate('content').exec((err, posts) => console.log("populated: ", posts))
res.redirect("/overview");
})

How do I query a specific Post by slug property value in mongoose instead of id?

I know how to query a specific post by id. However I want to use the slug property of the post instead of its id to to query it. How do I do so ?
//Instead of req.params.id, we have req.params.slug instead
//How do get the post in this case if the Post database model has a slug property.
//We have the req.params.slug
//This is what needs to be changed
const post = await Post.findById(req.params.id, (error, post) => {
console.log(error, post)
}).populate('author')
Here is the Post model:
const mongoose = require('mongoose')
const PostSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
subtitle: {
type: String,
required: true,
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
content: {
type: String,
required: true
},
image: String,
category: String,
subCategory: String,
createdAt: {
type: Date,
default: new Date()
}
})
module.exports = mongoose.model('Post', PostSchema)
you can use find() if you have many documents share the same slug or findOne() if this slug is unique for each document
Post.find({ slug: req.params.slug }, (error, post) => {
console.log(error, post)
});
or
Post.findOne({ slug: req.params.slug }, (error, post) => {
console.log(error, post)
});

Unable to delete a document in mongodb using DELETE method

I am new to node and mongodb, I have created a embedded/nested document, when I am trying to delete it using router.delete method its resulting in the following error: TypeError: Converting circular structure to JSON at JSON.stringify (). How to fix this and delete my document?
I tried with both findByIdAndRemove and findByIdAndDelete of the mongodb method.
**Article Schema**
const articleSchema = new mongoose.Schema({
articleName: {
type: String
},
author: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Author'
}],
comments: [commentSchema]
})
const Article = mongoose.model('Article', articleSchema)
**Route Delete Method**
router.delete('/:id', async (req, res) => {
const article = Article.findByIdAndDelete(req.params.id)
res.send(article)
})
**Comment Schema**
const commentSchema = new mongoose.Schema({
articles: {
type: new mongoose.Schema({
articleName: {
type: String
},
author: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Author'
}],
})
},
users: {
type: new mongoose.Schema({
name: String
})
},
comment: String
})
**User Schema**
const userSchema = new mongoose.Schema({name: String, email: String})
UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON at JSON.stringify (<anonymous>)
Are you missing await
**Route Delete Method**
router.delete('/:id', async (req, res) => {
const article = await Article.findByIdAndDelete(req.params.id)
res.send(article)
})

How do I join two mongodb collections together using a mongoose controller route?

Sorry, I'm pretty new with node.js and express. I'm trying to setup a mongoose schema that will allow a user to create a character and store that character in the collection associated with that User. I have two schemas, one for user and one for character.
So far, I have tried using .populate, I've tried pushing into the user array on my character schema. And it doesn't return the results i'm wanting.
Here are my schema's and my route file that should be setup to create a new user, and a character. But i'm not sure how to attach that newly created character to my user. When I tried some other variations, I was able to get a character ID to save in mongodb under a user but it would overwrite the current characterId already saved in there.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const characterSchema = new Schema({
name: {
type: String,
required: true,
},
job: {
type: String,
required: true,
},
race: {
type: String,
required: true,
},
level: {
type: String,
required: true,
},
image: {
type: String,
},
user: [{
type: schema.Types.ObjectId,
ref: 'User'
}]
});
const Character = mongoose.model('Character', characterSchema);
module.exports = Character;
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now
}
});
const User = mongoose.model('User', userSchema);
module.exports = User;
router.route('/').get((req, res) => {
User.find()
.then(users => res.json(users))
.catch(err => res.status(400).json("Error" + err))
});
router.route('/:id').get((req, res) => {
User.findById(req.params.id)
.then(user => res.json(user))
.catch(err => res.status(400).json("error" + err))
})
router.route('/character').get((req, res) => {
Character.find()
.then(characters => res.json(characters))
.catch(err => res.status(400).json("error" + err))
})
router.route('/character').post((req, res)=> {
const newCharacter = new Character({
name: req.body.name,
job: req.body.job,
race: req.body.race,
level: req.body.level
})
newCharacter
.save()
.then(character => res.json(character))
.catch(err => res.status(400).json("error" + err));
})
im not an expert in node.js nor in mongoose, but i have a little bit experiences.
For me it looks weird, because i think you use from user a reference to the character, or do i missunderstood something?
Because a user has a character.
For the handling:
If the User creates an character and post it, you get the user by the cookie, id or whatelse and then update the character.
Something like:
User.findOneAndUpdate(
{ "_id": userID},
{
"$set": {
"character.$": character
}
},
function(err,doc) {
}
);
So i think this is missing in Usermodel:
character: [{
type: schema.Types.ObjectId,
ref: 'Character'
}]

Problems with Mongoose populate

Game schema
const { Schema, model } = require('mongoose');
const gameSchema = Schema({
_id: Schema.Types.ObjectId,
name: { type: String, required: true },
description: String,
calc: [{ type: Schema.Types.ObjectId, ref: 'Calc' }]
});
module.exports = model('Game', gameSchema);
Calc schema
const { Schema, model } = require('mongoose');
const calcSchema = Schema({
_id: Schema.Types.ObjectId,
preset: { type: String, required: true },
datasets: [{ type: Schema.Types.ObjectId, ref: 'Dataset' }],
model: String,
});
module.exports = model('Calc', calcSchema, 'calc');
GET Games route
router.get('/', passport.authenticate('jwt', { session: false }), (req, res) => {
Game.find()
.select('_id name calc')
.populate('calc')
.then(games => res.status(200).json(games))
.catch(err => res.status(500).json({ error: err }));
});
Instead of populating calc property with Calc objects, replacing the ids, calc property turns into an empty array. How do I use populate correctly? Is there an obvious mistake I made in my code?
In short: populate() results in calc: [] instead of calc: [{Calc object}, ...]
In your case you are trying to populate an array of document (and not only one document) so you should use the Model.populate() method instead.
Game.find()
.select('_id name calc')
.then(games => Game.populate(games, { path: 'calc' }))
.then(games => res.status(200).json(games))
.catch(err => res.status(500).json({ error: err }));

Resources