猫鼬递归嵌套

Posted

技术标签:

【中文标题】猫鼬递归嵌套【英文标题】:mongoose recursive nesting 【发布时间】:2020-06-04 04:26:51 【问题描述】:

在我的项目中,用户可以创建产品。每个用户都有对其所有产品的引用,每个产品都有对其用户的引用。

用户和产品都有一个“名称”字段。

我需要获取所有用户产品数组,并且在该数组中我想要产品名称和 创建它的用户名(只有那些字段,没有其他字段)。

例如:

用户:

 _id: 1, name: 'josh', productIds: [1,3]
 _id: 2, name: 'sheldon', productIds: [2]

产品:

 _id: 1, name: 'table', price: 45, userId: 1
 _id: 2, name: 'television', price: 25 userId: 2
 _id: 3, name: 'chair', price: 14 userId: 1

我想得到以下结果:

 _id: 1, name: 'josh', 
    products: 
         _id: 1, name: 'table', user:  _id: 1, name: 'josh' ,
         _id: 3, name: 'chair', user:  _id: 1, name: 'josh' ,
    

 _id: 2, name: 'sheldon', 
    products: 
         _id: 2, name: 'television', userId:  _id: 2, name: 'sheldon' 
    

我尝试了以下未填充内部 userId 的查询,只留下了 id(无名称):

User.aggregate([
   
    $lookup: 
       
        from: 'products',
        localField: 'productIds',
        foreignField: '_id',
        as: 'products' 
        
  

我还尝试了以下方法,它与第一个查询相同,只是它只为每个用户重试了第一个产品:

User.aggregate([
   
    $lookup: 
       
        from: 'products',
        localField: 'productIds',
        foreignField: '_id',
        as: 'products' 
        
  ,
  
    $unwind: 
      path: "$products",
      preserveNullAndEmptyArrays: true
    
  ,
  
    $lookup: 
      from: "user",
      localField: "products.userId",
      foreignField: "_id",
      as: "prodUsr",
    
  ,
  
    $group: 
      _id : "$_id",
      products:  $push: "$products" ,
      "doc":  "$first": "$$ROOT" 
    
  ,
  
    "$replaceRoot": 
    "newRoot": "$doc"
    

产品:

const schema = new Schema(
  
    name: 
      type: String,
      required: true
    ,
    price: 
      type: Number,
      required: true
    ,
    userId: 
      type: Schema.Types.ObjectId, 
      ref: 'User',
      required: true
    ,
  
);

module.exports = mongoose.model('Product', schema);

用户:

const schema = new Schema(
  
    name: 
      type: String,
      required: true,
      unique: true
    ,
    productIds: [
      type: Schema.Types.ObjectId, 
      ref: 'Product',
      require: false
    ],
   timestamps: true 
);

module.exports = mongoose.model('User', schema);

我们将不胜感激任何帮助

【问题讨论】:

【参考方案1】:

对于$lookup with custom pipeline 和另一个嵌套的$lookup,这看起来是一个完美的场景。内层允许你处理product-> user 关系,而外层处理user -> product 一个:

db.Users.aggregate([
    
        $project: 
            productIds: 0
        
    ,
    
        $lookup: 
            from: "Products",
            let:  user_id: "$_id" ,
            pipeline: [
                
                    $match: 
                        $expr: 
                            $eq: [ "$userId", "$$user_id" ]
                        
                    
                ,
                
                    $lookup: 
                        from: "Users",
                        localField: "userId",
                        foreignField: "_id",
                        as: "user"
                    
                ,
                
                    $unwind: "$user"
                ,
                
                    $project: 
                        "user.productIds": 0,
                        "price": 0,
                        "userId": 0
                    
                
            ],
            as: "products"
        
    
])

Mongo Playground

【讨论】:

以上是关于猫鼬递归嵌套的主要内容,如果未能解决你的问题,请参考以下文章

无法查询嵌套的猫鼬数组?

猫鼬嵌套查询

在猫鼬中填充嵌套模型

在猫鼬中填充嵌套模型

猫鼬嵌套文档返回未定义

在猫鼬中发布嵌套模型