[英]Mongo Multiple Level Aggregate Lookup Group
我有 3 个 collections,用户、药房和城市。 我希望我的结果看起来像这样:
{
_id: ,
email: ,
birthdate: ,
type: ,
dispensary: {
_id: ,
schedule: ,
name: ,
address: ,
phone: ,
user:,
city: {
name:,
},
},
}
但是,我在第一级将城市 object 拿出来,我想把它作为药房集合的孩子。
这是我目前正在使用的管道:
User.aggregate
([
{
$match: { "_id": id }
},
{
$lookup:
{
from: Dispensary.collection.name,
localField: "dispensary",
foreignField: "_id",
as: "dispensary"
},
},
{"$unwind": {path:"$dispensary",preserveNullAndEmptyArrays: true} ,},
{
$lookup:
{
from: City.collection.name,
localField: "dispensary.city",
foreignField: "_id",
as: "city"
},
},
{"$unwind": {path:"$city",preserveNullAndEmptyArrays: true}} ,
{
"$group": {
_id: "$_id",
email : { $first: '$email' },
birthdate : { $first: '$birthdate' },
type : { $first: '$type' },
dispensary: { $push: "$dispensary" },
city: { $push: "$city" },
},
},
{"$unwind": {path:"$dispensary",preserveNullAndEmptyArrays: true}} ,
{"$unwind": {path:"$city",preserveNullAndEmptyArrays: true}} ,
], (aggErr, aggResult) => {
(aggErr) ? console.log(aggResult)
: console.log(aggResult)
})
架构:
const CitySchema = new Schema({
name: { type: String, required: true, unique:true },
zip: { type: String, required: true },
});
const DispensarySchema = new Schema({
name: { type: String, required: true },
address: { type: String, required: true },
longitude: { type: String, required: true },
latitude: { type: String, required: true },
phone: { type: String, required: true },
user: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
schedule: [{type: mongoose.Schema.Types.ObjectId, ref: 'Schedule'}],
city: {type: mongoose.Schema.Types.ObjectId, ref: 'City'},
})
const UserSchema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type:String, required: true },
birthdate: { type: Date, required: true },
type: { type: String, enum: ['ADMIN','DISPENSARY','CUSTOMER'], required: true},
verificationToken: { type: String, required: false },
resetPasswordToken: { type: String, required: false },
resetPasswordExpires: { type: String, required: false },
isVerified: { type: Boolean, required: true },
isActive: { type: Boolean, required: true },
last_session: { type: Date },
last_ip_session: { type:String },
dispensary: {type: mongoose.Schema.Types.ObjectId, ref: 'Dispensary'},
},
{ timestamps: true }
)
我认为您根本不需要使用$group
,您可以在第二个$lookup
中使用as: "dispensary.city"
[
{
"$match": {
"_id": id
}
},
{
"$lookup": {
from: Dispensary.collection.name,
localField: "dispensary",
foreignField: "_id",
as: "dispensary"
},
},
{
"$unwind": {
path: "$dispensary",
preserveNullAndEmptyArrays: true
},
},
{
"$lookup": {
from: City.collection.name,
localField: "dispensary.city",
foreignField: "_id",
as: "dispensary.city" // modify here
},
},
{
"$unwind": {
path: "$dispensary.city", // modify here
preserveNullAndEmptyArrays: true
}
}
]
您可以使用pipeline
使用另一种lookup
方法,这允许您在查找 function 中进行更多条件/子查询。 见参考: 聚合查找
User.aggregate([
{
$match: { "_id": id }
},
{
$lookup: {
from: Dispensary.collection.name,
let: {dispensaryId: "$dispensary"},
pipeline: [
{
$match: {
$expr: {
$eq: ["$_id", "$$dispensaryId"]
}
}
},
{
$lookup:
{
from: City.collection.name,
localField: "city",
foreignField: "_id",
as: "city"
},
},
{
$unwind: {
path:"$city",
preserveNullAndEmptyArrays: true
}
}
]
as: "dispensary",
},
},
{
$unwind: {
path:"$dispensary",
preserveNullAndEmptyArrays: true
}
},
{
"$group": {
_id: : {
_id: "$_id",
email : '$email' ,
birthdate : '$birthdate' ,
type : '$type'
dispensary: "$dispensary"
}
}
}
], (aggErr, aggResult) => {
(aggErr) ? console.log(aggResult)
: console.log(aggResult)
})
更新:管道注意:要在管道阶段引用变量,请使用“$$”语法。`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.