如果只有子文档元素在嵌套数组中匹配,则返回文档

问题描述

主要集合是用户,我们有一个用户个人资料集合,其中包含体验详细信息和其他内容。另外,我们还有一个技能集合。

用户

[{
    "_id": "5f1eef8ec68d306fbbf13b0f","name": "John Davis","email": "[email protected]","__v": 0
},{
    "_id": "9q1eef8ec68d306fbbf13bh6","name": "Mik Luca","email": "[email protected]","__v": 0
}]

用户个人资料

[{
        "_id": "5f1eef8ec68d306fbbf13b10","other_skills": [
            null
        ],"user_id": "5f1eef8ec68d306fbbf13b0f","phone_number": "1234569870","location": "5f16b72617fee02922688751","primary_skills": [
            {
                "_id": "5f32635cf764cc40447503a6","years": 1,"skill_id": "5f0da75907a96c3040b3667d"
            }
        ]
    },{
        "_id": "5f1eef8ec68d306fbbf13b10","user_id": "9q1eef8ec68d306fbbf13bh6","primary_skills": [
            {
                "_id": "6s0da75907a96c3040b36690","skill_id": "5f0da75907a96c3040b3667d"
            }
        ]
    }]

技能

[{  
    "_id": "5f0da75907a96c3040b3667d","skill": "Mongo"
},{  
    "_id": "6s0da75907a96c3040b36690","skill": "Node"
}]

我需要使用用户个人资料信息列出用户,并且还需要使用技能进行过滤

我尝试过

db.getCollection("users").aggregate(
    [
        { 
            "$project" : { 
                "_id" : NumberInt(0),"users" : "$$ROOT"
            }
        },{ 
            "$lookup" : { 
                "localField" : "users._id","from" : "userprofiles","foreignField" : "user_id","as" : "userprofiles"
            }
        },{ 
            "$unwind" : { 
                "path" : "$userprofiles","preserveNullAndEmptyArrays" : true
            }
        },{ 
            "$lookup" : { 
                "localField" : "userprofiles.primary_skills.skill_id","from" : "skills","foreignField" : "_id","as" : "skills"
            }
        },{ 
            "$unwind" : { 
                "path" : "$skills",{ 
            "$match" : { 
                "skills._id" : ObjectId("5f0dce8d07a96c3040b36687")
            }
        }
    ],{ 
        "allowdiskUse" : true
    }
);

但没有得到正确的结果。

如何使用用户列表填充用户个人资料技能信息,并使用技能ID过滤用户列表?

问候和感谢。

解决方法

您可以使用带有管道的查找来匹配查找中的过滤器,

  • $lookupuserProfile集合
  • 管道$match以匹配配置文件ID
  • skill_id之类的个人资料其他过滤器在这里匹配
  • $unwind解构primary_skills数组,因为我们要使用skill_id查找
  • $lookupskills收集
  • $unwind解构primary_skills.skill_id数组,因为我们需要它作为对象
  • $grpup重建primary_skills数组
  • $match,如果userProfiles不等于空的[]
db.users.aggregate([
  {
    $lookup: {
      from: "usersProfile",let: { id: "$_id" },as: "userProfiles",pipeline: [
        {
          $match: { 
             $expr: { $eq: ["$$id","$user_id"] },// match here user profile filters
            "primary_skills.skill_id": "5f0da75907a96c3040b3667d"
          }
        },{ $unwind: "$primary_skills" },{
          $lookup: {
            from: "skills",localField: "primary_skills.skill_id",foreignField: "_id",as: "primary_skills.skill_id"
          }
        },{ $unwind: "$primary_skills.skill_id" },{
          $group: {
            _id: "$_id",other_skills: { $first: "$other_skills" },phone_number: { $first: "$phone_number" },location: { $first: "$location" },primary_skills: {
              $push: {
                _id: "$primary_skills._id",skill: "$primary_skills.skill_id.skill",years: "$primary_skills.years"
              }
            }
          }
        }
      ]
    }
  },{ $match: { userProfiles: { $ne: [] } } }
])

Playground