sarvesh kumar
sarvesh kumar

Reputation: 213

Get Related schema fields from Mongoose in Node

I have created User Schema, I am storing user details with comments that are posted by different users.

Current Data Schema.

{
    _id: '1233333',
    name: 'John',
    profileImage: 'http:/test.com',
    coments: [{
            commentBy: ObjectId(UserId),
            comment: 'good '
        }, {
            commentBy: ObjectId(UserId),
            comment: 'good'
        }
    ]
}

When I fetch the user data I want to fetch user name, profile image URL inside comments Array, I am not storing the profileimageURL, name, because the user will update the user data any time.

I want Expected Data

{
    _id: '1233333',
    name: 'John',
    profileImage: 'http:/test.com',
    coments: [{
            commentBy: ObjectId(UserId),
            comment: 'good ',
            profileImage: 'http:/test.com',
            name : 'John'
        }, {
            commentBy: ObjectId(UserId),
            comment: 'good ',
            profileImage: 'http:/test.com',
            name : 'Tim'
        }
    ]
}

Please tell me the Query to fetch the data with one go.. Please advise

Upvotes: 1

Views: 328

Answers (2)

Talha Noyon
Talha Noyon

Reputation: 854

you can also achieve this without using aggregate sometimes aggregate pipeline works slow. In your user schema, you can use the virtual population. like this

UserSchema.virtual('commentBy',{
    ref: 'user',//this the collection name
    localField: 'coments.commentBy',
    foreignField: '_id',
    justOne:true
});

UserSchema.set('toObject', { virtuals: true });
UserSchema.set('toJSON', { virtuals: true });

then find and populate it this way

UserModel.find({})
      .lean()
      .populate('commentBy')
      .then((data) => {
        if (data.length > 0) {
          result(data);
        } else {
          console.log("Data Not Exists");
        }
      });

Upvotes: 0

Ana Lava
Ana Lava

Reputation: 787

You can handle this situation with mongo aggregation as below:

db.getCollection('user').aggregate([

  { $unwind: { path: '$coments' } },
  
  { $lookup: {
        from: 'user',
        localField: 'coments.commentBy',
        foreignField: '_id',
        as: 'commentBy',
      }
    }, 

  { $unwind: { path: '$commentBy' } },

  { $group: {
    _id: '$_id',
    name: { $first: '$name' } ,
    profileImage: { $first: '$profileImage' },
    coments: { $push: {
                      commentBy: "$coments.commentBy",
                      comment: "$coments.comment",
                      profileImage: "$commentBy.profileImage",
                      name: "$commentBy.name"} 
              } 
    }}])

First, you unwind coments array (The spelling is wrong in your sample) to have each comment in a seperate document. Then you can use $lookup to extract the user who is declared in commentBy field. Afterwards you group the documents together with the desired format.

Upvotes: 1

Related Questions