[英]MongoDB query based on multiple joins
关于联接和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'
}]
})
想象一下这已经在生产中,并且不可能更改架构。
我怎么能找回所有带有至少一只“贵宾犬”犬种的犬 ,并且教练的性别是“雄性”的 犬队?
用另一种方式提出您的问题:如何在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
“ male”的结果集 最终结果将如下所示:
{
"_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
是dog not team的_id,因此从技术上讲,结果集包含包含团队和训练员的dogs,但是您可以将它们视为“团队”文档。 您可以从Person
到Dog
进行另一种方式。
而且,结果的结构也不完美。 您可能想要一种结构良好的格式,因为人口喜欢包含嵌入式trainer
和members
teams
。 通过对聚合管道进行一些调整,我确信可以实现结构良好的结构。
最后,这不同于猫鼬的人口,这是另一个答案。 主要区别在于,在这种情况下,您已经将查找所需文档的任务委派给了mongo服务器,并且显然是一次完成的任务。 就人口而言,同样需要太多的客户端处理和对db的许多请求。 但是$ lookup适用于未分片的集合,在这种情况下,您可能更喜欢填充或考虑此答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.