关于连接和MongoDB有很多问题,但是很多问题已经过时了,考虑到Mongo 3.x之后没有采用功能的答案。我的问题是你如何查询具有链接元素条件的表?
这是一个极其简化的例子
const Person = new mongoose.Schema({
gender: String
});
const Dog = new mongoose.Schema({
breed: String
});
const Team = new mongoose.Schema({
trainer: {
type: mongoose.Schema.ObjectId,
ref: 'Person'
},
members: [{
type: mongoose.Schema.ObjectId,
ref: 'Dog'
}]
})
想象一下,这已经在制作中,并且不可能改变架构。
如何检索所有至少有一只“Poodle”品种的成员狗以及,其中培训师的性别是“男性”?
答案 0 :(得分:2)
以不同的方式提出问题:如何在mongoDB中加入两个以上的集合?
假设您针对模型名称的集合名称为dogs
,teams
和people
(Mongoose复数约定),以下是实现所需结果的方法之一:
Dog.aggregate([{
$match: {
breed: "Poodle"
}
},
{
$lookup: {
from: "teams",
localField: "_id",
foreignField: "members",
as: "team"
}
},
{
$unwind: "$team"
},
{
$lookup: {
from: "people",
localField: "team.trainer",
foreignField: "_id",
as: "trainer"
}
},
{
$unwind: "$trainer"
},
{
$match: {
"trainer.gender": "male"
}
},
{
$project: {
breed: 1,
trainer: 1,
team: {
_id: 1
}
}
}
], function(err, teams) {
console.log(teams)
});
在汇总管道中,我们执行以下操作:
Dog
为起点并匹配品种trainer.gender
"男" 最终结果将如下所示:
{
"_id" : ObjectId("596e5500b5174986059958a8"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958de")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
{
"_id" : ObjectId("596e5500b5174986059958a8"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958e6")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
{
"_id" : ObjectId("596e5500b5174986059958b2"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958de")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
{
"_id" : ObjectId("596e5500b5174986059958b2"),
"breed" : "Poodle",
"team" : {
"_id" : ObjectId("596e564fb5174986059958e6")
},
"trainer" : {
"_id" : ObjectId("596e54bfb51749860599589c"),
"gender" : "male"
}
}
基本上,我们搜索了Dog
并加入并匹配了更多的收藏品。最终文档中的根_id
是狗而不是团队的_id,因此从技术上讲,结果集包含包含团队和培训师的狗,但您可以将其视为"团队"文献。你可以反过来,从Person
开始到达Dog
。
此外,结果的结构并不完美。您可能想要一个结构良好的格式,因为人口与包含嵌入式teams
和trainer
的{{1}}类似。通过聚合管道中的一些调整,我确信可以实现良好的结构。
最后,这与Mongoose人口不同,这是另一个答案。主要的区别在于,在这种情况下,您已将完成所需文档的任务委派给mongo服务器,显然是一气呵成。在人口中,同样需要过多的客户端处理和对db的许多请求。但是$lookup适用于未加密的收集,在这种情况下,您可能更喜欢人口或考虑this回答。