数组内子字段的聚合查找

问题描述 投票:0回答:1

我有以下用于用户集合的 MongoDB 架构

{
...otherProperties,
skills: [
{
    skill: { type: db.Schema.Types.ObjectId, ref: 'Skill' },
    level: { type: String }
}
]
}

我正在尝试使用聚合将此集合加入到技能集合中 但我想保留另一个字段

level
并将每个字段与其对象连接起来 我尝试过以下聚合

[{$lookup:{ from: 'Skill',localField: 'skills.skill', foreignField: '_id', as: 'skills.skill' }}]

我得到的结果如下

{
  "_id": {
    "$oid": "6130f296eff45efaa80cb4e6"
  },
  "skills": {
    "skill": [
      {
        "_id": {
          "$oid": "60d9a0996e5c5f0025f3c882"
        },
        "job_post_enabled": true,
        "job_seeker_enabled": true,
        "job_seeker": "A/R Management",
        "job_post": "A/R Management",
        "__v": 0,
        "translations": {
          "AR": {
            "job_post": "A/R Management",
            "job_seeker": "A/R Management"
          },
          "EN": {
            "job_post": "A/R Management",
            "job_seeker": "A/R Management"
          }
        },
        "created_at": {
          "$date": "2021-06-28T10:12:58.221Z"
        },
        "updated_at": {
          "$date": "2022-01-25T21:52:55.447Z"
        }
      },
      {
        "_id": {
          "$oid": "60d9a0996e5c5f0025f3c886"
        },
        "job_post_enabled": true,
        "job_seeker_enabled": true,
        "job_seeker": "A/V systems",
        "job_post": "A/V systems",
        "__v": 0,
        "translations": {
          "AR": {
            "job_post": "A/V systems",
            "job_seeker": "A/V systems"
          },
          "EN": {
            "job_post": "A/V systems",
            "job_seeker": "A/V systems"
          }
        },
        "created_at": {
          "$date": "2021-06-28T10:12:58.221Z"
        },
        "updated_at": {
          "$date": "2022-01-25T21:52:55.453Z"
        }
      }
    ]
  }
}

有没有办法使用聚合将每个技能与其自己的记录连接起来?并保持字段原样

我目前的数据

{
    "skills": [
        {
            "skill": ObjectId("60d9a0996e5c5f0025f3c882"),
            "level": "High"
        },
        {
            "skill": ObjectId("60d9a0996e5c5f0025f3c886"),
            "level": "Mid"
        }
    ]
}

所需的输出

{
    "skills": [
        {
            "skill":       {
                "_id": {
                  "$oid": "60d9a0996e5c5f0025f3c882"
                },
                "job_post_enabled": true,
                "job_seeker_enabled": true,
                "job_seeker": "A/R Management",
                "job_post": "A/R Management",
                "__v": 0,
                "translations": {
                  "AR": {
                    "job_post": "A/R Management",
                    "job_seeker": "A/R Management"
                  },
                  "EN": {
                    "job_post": "A/R Management",
                    "job_seeker": "A/R Management"
                  }
                },
                "created_at": {
                  "$date": "2021-06-28T10:12:58.221Z"
                },
                "updated_at": {
                  "$date": "2022-01-25T21:52:55.447Z"
                }
              },
              "level": "High"
        },
        {
            "skill": {
                "_id": {
                  "$oid": "60d9a0996e5c5f0025f3c886"
                },
                "job_post_enabled": true,
                "job_seeker_enabled": true,
                "job_seeker": "A/V systems",
                "job_post": "A/V systems",
                "__v": 0,
                "translations": {
                  "AR": {
                    "job_post": "A/V systems",
                    "job_seeker": "A/V systems"
                  },
                  "EN": {
                    "job_post": "A/V systems",
                    "job_seeker": "A/V systems"
                  }
                },
                "created_at": {
                  "$date": "2021-06-28T10:12:58.221Z"
                },
                "updated_at": {
                  "$date": "2022-01-25T21:52:55.453Z"
                }
              },
            "level": "Mid"
        }
    ]
}
mongodb aggregate lookup
1个回答
0
投票

解决方案,但需要注意技能_id应该存在于查找集合中;否则,技能 _id 将不会出现在输出中,即没有立即的方法来告诉缺少某些内容。

c = db.foo.aggregate([
    // Optional match here:                                                                                                    
    //{$match: {_id:0}},                                                                                                       

    // Do the basic lookup:                                                                                                    
    {$lookup: {
        from: "Xskills",
        localField: "skills.skill",
        foreignField: "_id",
        as: "zz"
        }}

    // zz now contains an array of zero to N matches against the skills                                                        
    // table.  Use $zip to merge the separate skills and detail array fields, e.g.                                                        
    //   {                                                                                                                     
    //     skills: [ {skill:"S1",level:"High"},                                                                                
    //     zz:     [ {job_seeker:"whatever",job_post_enabled:true,...}, {QQQ} ]                                                
    // becomes an array of arrays [ [skill,detail], [skill,detail], ...]                                                                                                               
    //   {                                                                                                                     
    //     skills: [ [ {skill:"S1",level:"High"}, {job_seeker:"whatever",job_post_enabled:true,...} ], [ {skill:"S2",level:"Mid"}, {job_seeker:"whatever",job_post_enabled:true,...} ] ]                                                                     
    //   }                                                                                                                     

    ,{$project: {
        "skills": {$zip: {inputs: [ "$skills", "$zz" ]}}
    }}

    // Now we have a single array field with a well-known structure that we can                                                
    // reformat to produce the output we seek:                                                                                 
    ,{$project: {
        "skills": {$map: {input: "$skills", in:
                          {
                              "skill": {$arrayElemAt:["$$this",1]},
                              "level": {$arrayElemAt:["$$this.level",0]}
                          }
                         }}
    }}
]);
© www.soinside.com 2019 - 2024. All rights reserved.