Return 文档如果只有子文档元素在嵌套数组中匹配

Return document if only sub-document elements matched within a nested array

主要集合是 User,我们有一个 User profile 集合,其中包含体验详情和其他内容。此外,我们还有一个 技能 集合。

用户

[{
    "_id": "5f1eef8ec68d306fbbf13b0f",
    "name": "John Davis",
    "email": "John@gmail.com",
    "__v": 0
},
{
    "_id": "9q1eef8ec68d306fbbf13bh6",
    "name": "Mik Luca",
    "email": "Mik@gmail.com",
    "__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",
        "other_skills": [
            null
        ],
        "user_id": "9q1eef8ec68d306fbbf13bh6",
        "phone_number": "1234569870",
        "location": "5f16b72617fee02922688751",
        "primary_skills": [
            {
                "_id": "6s0da75907a96c3040b36690",
                "years": 1,
                "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", 
                "preserveNullAndEmptyArrays" : true
            }
        }, 
        { 
            "$match" : { 
                "skills._id" : ObjectId("5f0dce8d07a96c3040b36687")
            }
        }
    ], 
    { 
        "allowDiskUse" : true
    }
);

但没有得到正确的结果。

如何使用 User 列表填充 user profileskill 信息以及使用技能 ID 过滤用户列表?

问候和感谢。

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

  • $lookupuserProfile collection
  • 管道 $match 以匹配配置文件 ID
  • skill_id 这样的配置文件的其他过滤器在此处匹配
  • $unwind 解构 primary_skills 数组,因为我们要使用 skill_id
  • 进行查找
  • $lookupskills collection
  • $unwind 解构 primary_skills.skill_id 数组,因为我们需要它作为 object
  • $grpup重构primary_skills数组
  • $match if 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