0

i'm facing a problem that i'm not able to solve, i've created an express API with mongoose, with 2 models "Posts" and "users"

what i want is that if i perform a GET request to /posts return a lists of posts with the related author, and if i perform a GET request to /users return a lists of users with the related posts

well, the first one works fine, the "authors" is populated correctly.

the second one return always the "posts" array empty.

here my posts model:

const mongoose = require('mongoose')

const PostsModel = new mongoose.Schema({
    title: {
        type: String,
        required: true,
    },
    content: {
        type: String,
        required: true,
    },
    img: {
        type: String,
        required: false,
        default: 'https://picsum.photos/1920/1080',
    },
    author: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'userModel',
    },
    rate: {
        type: Number,
        required: false,
    },
}, { timestamps: true, strict: true });

module.exports = mongoose.model('postsModel', PostsModel, 'posts');

and here my Users model:

const mongoose = require('mongoose');


const UserSchema = new mongoose.Schema({
    firstName: {
        type: String,
        required: true,
        max: 255
    },
    lastName: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        required: true,
    },
    password: {
        type: String,
        required: true,
    },
    role: {
        type: String,
        required: false,
        default: 'user'
    },
    age: {
        type: Number,
        required: false,
        default: 0
    },
    posts: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'postsModel',
    }],
}, {
    timestamps: true, strict: true
})

module.exports = mongoose.model('userModel', UserSchema, 'users' )

and here the respective GET

router.get('/posts', async (req, res) => {
    const {page = 1, pageSize = 10} = req.query
    try {
        const post = await PostsModel.find()
            .populate('author', 'firstName lastName age email')
            .limit(pageSize)
            .skip((page - 1) * pageSize)

        const totalPosts = await PostsModel.count();

        res.status(200).send({
            count: totalPosts,
            currentPage: +page,
            totalPages: Math.ceil(totalPosts / pageSize),
            statusCode: 200,
            post
        })
    } catch (error) {
        res.status(500)
            .send({
                statusCode: 500,
                message: 'Errore interno del server'
            })
    }
})
router.get('/users',  async (req, res) => {
    const { page = 1, pageSize = 30 } = req.query
    try {
        const users = await UsersModel.find()
            .populate('posts', 'title content')
            .limit(pageSize)
            .skip((page - 1) * pageSize)

        const totalUsers = await UsersModel.count()

        res.status(200).send({
            count: totalUsers,
            currentPage: page,
            totalPages: Math.ceil(totalUsers / pageSize),
            pageSize,
            users
        })
    } catch (error) {
        res.status(500)
            .send({
                message: 'Errore interno del server'
            })
    }
})

All seems correct but for some reason, i get always the array empty.

2 Answers2

1

Your routes and models seems to be ok. I guess you are not adding the post._id to the user.posts array when you create the Post. If you add the created post._id to the user posts correctly, it should work.

The code should be something like this:

    const newPost = await PostsModel.create(req.body);

    const userPush = await UsersModel.findByIdAndUpdate(req.body.author, {
        $push: {
            posts: newPost._id,
        },
    });
SuleymanSah
  • 17,153
  • 5
  • 33
  • 54
  • following your suggestion i get alwayt the empty array, heres the try that i've made https://jsfiddle.net/51hcnosy/ – Marco Colia May 26 '23 at 15:19
0

I've found a solution by myself, if someone need the answer is:

in the userSchema simply add:

posts: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'postsModel',
        default: []
    }]

and then when the new post is created

router.post('/posts/new', async (req, res) => {
    const user = await UsersModel.findOne({ _id: req.body.author });

    const newPost = new PostsModel({
        title: req.body.title,
        content: req.body.content,
        author: user._id,
        img: req.body.img,
        rate: req.body.rate,
    })


    try {
        const post = await newPost.save()
        await UsersModel.updateOne({ _id: user._id }, {$push: {posts: post }})
        res.status(200)
            .send({
                message: 'Post salvato correttamente',
                statusCode: 200,
                post
            })
    } catch(error) {
        res.status(500)
            .send({
                message: 'Errore interno del server',
                statusCode: 500
            })
    }
})
  • This is effectively the same as my answer. You just used updateOne instead of findByIdAndUpdate which does the same. – SuleymanSah May 26 '23 at 16:11