Search code examples
javascriptnode.jsmongodbmongoose

How to Get Data from another collection in mongodb?


For example, my teacher collection documents look like:

{ _id: new ObjectId("64fee9b54273ac223441225"), teacherid: '64f1d72a4331bc8fc4c5930f', name: 'Jackly' }

and the users collection documents look like:

{ _id: new ObjectId("64f1d72a4331bc8fc4c5930f"), name: 'Mark' }

How can I get the name from users collection by the teacherid in the teacher collection? in MongoDB?

const studentData = await Teacher.aggregate([
    {
        $match: {
            "_id": "64f1d72a4331bc8fc4c5930f"
        }
    },
    {
        $lookup: {
            from: "users",
            localField: "teacherid",
            foreignField: "_id",
            as: "student"
        }
    },
    {
        $unset: "name"
    }
]);

Solution

  • the issue is that the two fields you are trying to compare are of 2 types. One is a string other is ObjectID. I would recommend to have both of them a single type (preferrably ObjectID) when storing so you don't have to do these intermediate transformations.

    however there are a couple of ways of doing this

    1. Transforming the teacherid to ObjectID and then $lookup. This will however have the teacherid as an ObjectID in the queried result. If you dont want it that way you might have to do an $addFields again and convert back to string
    db.teacher.aggregate([
      { $match: { teacherid: "64f1d72a4331bc8fc4c5930f" } },
      { $addFields: { teacherid: { $toObjectId: "$teacherid" } } },
      { $lookup: { from: "users", localField: "teacherid", foreignField: "_id", as: "student" } },
      { $unset: "name" }
    ])
    

    demo

    1. Transforming the teacherid to ObjectID in the lookup pipeline itself and compairing
    db.teacher.aggregate([
      { $match: { "teacherid": "64f1d72a4331bc8fc4c5930f" } },
      {
        $lookup: {
          from: "users",
          let: { teacherIdStr: "$teacherid" },
          pipeline: [
            {
              $match: {
                $expr: { $eq: [ "$_id", { $toObjectId: "$$teacherIdStr" } ] }
              }
            }
          ],
          as: "student"
        }
      },
      { $unset: "name" }
    ])
    

    demo

    1. Or convert the foreign field ObjectID to string and match
    db.teacher.aggregate([
      { $match: { "teacherid": "64f1d72a4331bc8fc4c5930f" } },
      {
        $lookup: {
          from: "users",
          let: { teacherIdStr: "$teacherid" },
          pipeline: [
            {
              $match: { 
                $expr: { $eq: [ { $toString: "$_id" }, "$$teacherIdStr" ] } 
              }
            }
          ],
          as: "student"
        }
      },
      { $unset: "name" }
    ])
    

    demo