Search code examples
mongodbmongooselookupaggregation

MongoDB aggregate lookup not working for post comments


I have two collections where need to lookup on aggregate.That's pretty straightforward where posts need to lookup comments on listing.

Here I defined Content schema -

const ContentSchema = new Schema({
    .........
    linkName: {
        type: String,

    },
    description: {
        type: String,
    }
},
{
    timestamps: true 
});
module.exports = mongoose.model('Content', ContentSchema);

Comment schema contentComment -

const contentCommentSchema = new Schema({
    ........
    content: {
        type: Schema.Types.ObjectId,
        ref: 'Content'
    }
},
{
    timestamps: true
});
module.exports = mongoose.model('contentComment', contentCommentSchema);

Here is the query where I am trying to list posts(Content schema) with corresponding comments from contentComment -

const contentPromise = Content.aggregate([
    {
        $lookup: {
            from: 'contentComments',
            let: { contentId: '$_id' },
            pipeline: [{
                $match: {
                    $expr: {
                        $eq: [ '$content', '$$contentId' ]
                    }
                } 
            }],
            as: 'nbComments'
        }
        .......
    }
]);

Also I tried with following $lookup -

const contentPromise = Content.aggregate([
    {
        $lookup: {
            from: "contentComments",
            localField: "_id",
            foreignField: "content",
            as: "nbComments"
        }
        .......
    }
];

But every time it returns empty array for comments.

Here are two screenshots of MongoDB Compass for contents -

content documents

and contentComments -

content comments documents

I can't figure out the issue for returning empty error for nbComments even though there are sufficient comments for a specific post/content. Here is a screenshot -

empty result for nbComments


Solution

  • from is using plurals lowercase collection name, as you use in mongo terminal.

    So you have to use contentcomments and not contentComments

    You can either use contentComment.collection.name

    Example:

    const AwesomeNameSchema = new Schema({
    =   
    });
    module.exports = mongoose.model('AwesomeName', AwesomeNameSchema);
    

    In mongo terminal

    db.AwesomeName.count(); // return 0, not working
    db.AwesomeNames.count(); // return 0, not working
    db.awesomename.count(); // return 0, not working
    
    db.awesomenames.count(); // return X, working solution
    

    In mongoose lookup

    var AwesomeName = require("./models/AwesomeName.js");
    var ParentAwesomeName = require("./models/ParentAwesomeName.js");
    
    // not working
    ParentAwesomeName.aggregate([
        {
            $lookup: {
                from: "AwesomeNames",
                localField: "_id",
                foreignField: "awesome_name",
                as: "awesome"
            }
            .......
        }
    ]; 
    
    // working
    ParentAwesomeName.aggregate([
        {
            $lookup: {
                from: "awesomenames",
                localField: "_id",
                foreignField: "awesome_name",
                as: "awesome"
            }
            .......
        }
    ]; 
    
    // working
    ParentAwesomeName.aggregate([
        {
            $lookup: {
                from: AwesomeName.collection.name,
                localField: "_id",
                foreignField: "awesome_name",
                as: "awesome"
            }
            .......
        }
    ];