繁体   English   中英

Mongo 多级聚合查找组

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM