javascript 如何在mongodb中从另一个集合中获取数据?

slmsl1lt  于 2023-09-29  发布在  Java
关注(0)|答案(3)|浏览(92)

例如,我的教师集合文档看起来像:

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

用户集合文档如下所示:

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

如何通过教师集合中的teacherid从用户集合中获取名称?在MongoDB?

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

7ajki6be1#

问题是您尝试比较的两个字段属于2种类型。一个是字符串,另一个是ObjectID。我建议在存储时将它们都设置为单一类型(最好是ObjectID),这样就不必进行这些中间转换。
但是有几种方法可以做到这一点
1.将teacherid转换为ObjectID,然后转换为$lookup。但是,这将使teacherid作为查询结果中的ObjectID。如果您不想这样做,您可能需要再次执行$addFields并转换回字符串

db.teacher.aggregate([
  { $match: { teacherid: "64f1d72a4331bc8fc4c5930f" } },
  { $addFields: { teacherid: { $toObjectId: "$teacherid" } } },
  { $lookup: { from: "users", localField: "teacherid", foreignField: "_id", as: "student" } },
  { $unset: "name" }
])

demo
1.在查找管道本身中将teacherid转换为ObjectID并比较

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.或将外部字段ObjectID转换为字符串并匹配

db.teacher.aggregate([
  { $match: { "teacherid": "64f1d72a4331bc8fc4c5930f" } },
  {
    $lookup: {
      from: "users",
      let: { teacherIdStr: "$teacherid" },
      pipeline: [
        {
          $match: { 
            $expr: { $eq: [ { $toString: "$_id" }, "$$teacherIdStr" ] } 
          }
        }
      ],
      as: "student"
    }
  },
  { $unset: "name" }
])

demo

11dmarpk

11dmarpk2#

快速修复方案

1.将字符串id teacherid更改为ObjectId

$ mongo

# replace the `YOUR_DATABASE_NAME` with your real database name.
> use YOUR_DATABASE_NAME

# update Teacher collection ✅
> db.Teacher.update(
  {"teacherid" : "64f1d72a4331bc8fc4c5930f"},
  {
    $set: {"teacherid" : ObjectId("64f1d72a4331bc8fc4c5930f")}
  });

1.然后使用teacherid作为匹配键

> db.Teacher.aggregate([
    {
        $match: {
            "teacherid": ObjectId("64f1d72a4331bc8fc4c5930f")
        }
    },
    {
        $lookup: {
            from: "user",
            localField: "teacherid",
            foreignField: "_id",
            as: "student"
        }
    },
    {
        $unset: "name"
    }
]).pretty();

测试

截图

vfh0ocws

vfh0ocws3#

看起来您正在尝试使用MongoDB聚合框架,根据“teacherid”字段在“teacher”和“users”集合之间执行查找。但是,您当前的聚合管道存在一些问题。以下是聚合查询的更正版本:

const studentData = await Teacher.aggregate([
    {
        $match: {
            "_id": new ObjectId("64f1d72a4331bc8fc4c5930f") // Convert the ID to ObjectId
        }
    },
    {
        $lookup: {
            from: "users",
            localField: "teacherid",
            foreignField: "_id",
            as: "student"
        }
    },
    {
        $unwind: "$student" // Unwind the "student" array
    },
    {
        $project: {
            "student.name": 1 // Project the "name" field from the "student" subdocument
        }
    }
]);

console.log(studentData);

以下是对所做更改的解释:
1.在$match阶段,您需要使用new ObjectId()_id值转换为ObjectId,以匹配“teacher”集合中的正确文档。
1.在$lookup阶段之后,您有一个名为“student”的数组,其中包含匹配的用户文档。要访问“student”子文档中的“name”字段,需要使用$unwind stage来解构数组。
1.最后,您可以使用$project stage仅投影“student”子文档中的“name”字段。
现在,studentData应该包含“users”集合中的“name”字段,用于“teacher”集合中指定的教师ID。

相关问题