Search code examples
javascriptnode.jsmongodbmongoose

Mongoose retrieve all documents that are not referenced in the same collection's array field


I have the below Post schema. The post schema contains an array field that may contain other posts as replies. What I would like to do is retrieve all documents which are not referenced in any post's replies field. Basically get all posts that are not replies of an original post.

const mongoose = require('mongoose');

const schema = new mongoose.Schema({
    creator: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        validate: [mongoose.Types.ObjectId.isValid, 'Creator ID is invalid']
    },
    owner: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        validate: [mongoose.Types.ObjectId.isValid, 'Owner ID is invalid']
    },
    content: {
        type: String,
        required: 'Content is required'
    },
    likes: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Like',
            validate: [mongoose.Types.ObjectId.isValid, 'Like ID is invalid']
        }
    ],
    replies: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Post'
        }
    ]
}, {
    autoCreate: true,
    timestamps: true
});

const Post = mongoose.model('Post', schema);

module.exports = Post;

I have tried using $lookup with $match & $nin but I cannot make it work properly. Any help would be greatly appreciated.


Solution

  • IF I'm not mistaken this seems to work:

                let posts = await MODELS.Post.aggregate([
                    {
                        $lookup: {
                            from: 'posts',
                            localField: '_id',
                            foreignField: 'replies',
                            as: 'references'
                        }
                    },
                    {
                        '$match': {
                            'references._id': {
                                '$exists': false
                            }
                        }
                    },
                    {
                        '$sort': {
                            createdAt: -1
                        }
                    },
                    {
                        '$project': { 
                            references: false
                        }
                    },
                    {
                        '$limit': 10
                    }
                ]);