我在mongodb中相当陌生,我有一个名为message的集合,其中包含一个字段名称usrId。该字段可以引用学生或管理员。因此,我将3个表分别与message和student和chatAdmin结合在一起,以找出此消息是由谁发送的。
但是问题是,我不想在结果字段中使用2个单独的对象。我只想让一个用户对象包含Student或admin。因为消息仅来自其中之一。
消息收集:
{
"_id" : ObjectId("5c73d1aec058ed1b1ce0acb4"),
"msg" : "test",
"usrId" : ObjectId("5c63f0f1dcebbc69fba10db5"),
"chId" : ObjectId("5c7121b794b7b935e41568b3"),
"pinned" : false,
"warned" : false,
"marked" : false
}
我尝试过的代码:
con.collection("message").aggregate([
{$match: {"chId": chId}},
{
$lookup: {
from: "student",
localField: "usrId",
foreignField: "_id",
as: "student"
}
},
{ $unwind: { path: "$student", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "chatAdmin",
localField: "usrId",
foreignField: "_id",
as: "chAdmin"
}
},
{ $unwind: { path: "$chAdmin", preserveNullAndEmptyArrays: true } },
])
我想要的结果是:
{
"_id" : ObjectId("5c73d1aec058ed1b1ce0acb4"),
"msg" : "test",
"usrId" : ObjectId("5c63f0f1dcebbc69fba10db5"),
"chId" : ObjectId("5c7121b794b7b935e41568b3"),
"pinned" : false,
"warned" : false,
"marked" : false,
"user"{ "role":"student" , image :"" , "name":"test"}
}
或者如果发件人是admin:
{
"_id" : ObjectId("5c73d1aec058ed1b1ce0acb4"),
"msg" : "test",
"usrId" : ObjectId("5c63f0f1dcebbc69fba10db5"),
"chId" : ObjectId("5c7121b794b7b935e41568b3"),
"pinned" : false,
"warned" : false,
"marked" : false,
"user"{ "role":"admin" , image :"" , "name":"test"}
}
答案 0 :(得分:1)
您应该考虑自己的设计。 MongoDB不是关系数据库,因此您没有表,并且通常希望避免将联接作为主要模式,尤其是当您有大数据时。
最好阅读有关NoSQL数据库的非规范化的信息。例如,最好让学生和管理员都在同一个集合中。甚至最好不要进行联接,而是将它们的数据或简短信息嵌入,在大多数情况下,这对于您在消息集合中足够了。这是重复的,但是您获得的延迟很短,这就是NoSQL数据库的全部目的。另外,您可能会考虑使用常规的关系数据库。
可以说,为了学习,您可以执行以下操作:
$addFields: {
user: {
$cond: [
{$ifNull: ['$student', false]},
{role: 'admin', image: $chAdmin.image, name: $chAdmin.name},
{role: 'student', image: $student.image, name: $student.name}
]
}
}