猫鼬加入两个集合并在两个属性中获取引用数据

时间:2020-10-13 16:27:05

标签: node.js mongodb mongoose

我正在做一个简单的关注好友功能。

请在下面查看我的代码:

以下架构:

{
 "userId": { type: String },
 "followers": [{ "followerId": type: String }],
 "followings": [{ "followingId": type: String }], 
}

用户架构:

{
 "fullName": { type: String } 
}

注意:用户8具有1个关注者和2个关注。

现在,我的预期输出应该是这样的:

        "userId": 8,
        "followers": [
            {
                "followerId": 4,
                "fullName": "Rose Marriott",
            },
            {
                "followerId": 5,
                "fullName": "James Naismith",
            }
        ],
        "followings": [
            {
                "followingId": 1,
                "fullName": "Russell Oakham",
            },
            {
                "followingId": 5,
                "fullName": "James Naismith",
            }
        ]

这是我到目前为止尝试过的:

 db.followings.aggregate([
 { $unwind: "$followers" },
    {
        $lookup: {
            from: "users",
            localField: "followers.followerId",
            foreignField: "_id",
            as: "users"
        }
    },
    { 
        $addFields: 
        { 
            users: { $arrayElemAt: ["$users", 0] },
        },
    },
    { $unwind: "$followings" },
    {
        $lookup: {
          from: "users",
          localField: "followings.followingId",
          foreignField: "_id",
          as: "users2"
        }
    },
    { 
        $addFields: 
        { 
            users2: { $arrayElemAt: ["$users2", 0] },
        },
    },
    { $match: {"userId": mongoose.Types.ObjectId(userId) } },
    {
        $group: {
            _id: "$_id",
            userId: { $first: "$userId" },
            followers: {
                $push: {
                    followerId: "$followers.followerId",
                    fullName: "$users.fullName",
                }
            },
            followings: {
                $push: {
                    followingId: "$followings.followingId",
                    fullName: "$users2.fullName",
                }
            }
        }
      }
  ]);

但是我有2个关注者和2个关注者。我想知道是什么导致了这个问题。感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:0)

您可以尝试

  • $addFields组成一个名为userIds的唯一数组,同时形成两个数组followersfollowings$setUnion以获得唯一的ID,
  • $lookup和用户集合
  • $project以显示字段,
    • followers获取fullName,$ map来迭代followers的循环,并使用followerId$reduce $cond的名称>
    • followings获取fullName,$ map以迭代followings的循环,并使用followingId$reduce $cond的名称>
db.followings.aggregate([
  {
    $addFields: {
      userIds: {
        $setUnion: [
          {
            $map: {
              input: "$followers",
              in: "$$this.followerId"
            }
          },
          {
            $map: {
              input: "$followings",
              in: "$$this.followingId"
            }
          }
        ]
      }
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "userIds",
      foreignField: "_id",
      as: "users"
    }
  },
  {
    $project: {
      userId: 1,
      followers: {
        $map: {
          input: "$followers",
          as: "f",
          in: {
            $mergeObjects: [
              "$$f",
              {
                fullName: {
                  $reduce: {
                    input: "$users",
                    initialValue: "",
                    in: {
                      $cond: [
                        { $eq: ["$$this._id", "$$f.followerId"] },
                        "$$this.fullName",
                        "$$value"
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      },
      followings: {
        $map: {
          input: "$followings",
          as: "f",
          in: {
            $mergeObjects: [
              "$$f",
              {
                fullName: {
                  $reduce: {
                    input: "$users",
                    initialValue: "",
                    in: {
                      $cond: [
                        { $eq: ["$$this._id", "$$f.followingId"] },
                        "$$this.fullName",
                        "$$value"
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Playground

答案 1 :(得分:0)

在Mongoose上处理关系时,应基于唯一ID创建关系,然后引用文档。在您的情况下,应该是:

followingSchema = new mongoose.Schema({
    {
     "followers": [{type: mongoose.Schema.types.ObjectId, ref="User"}],
     "followings": [{type: mongoose.Schema.types.ObjectId, ref="User"}], 
    }
})

userSchema = new mongoose.Schema({
    fullname: String,
})

请注意,Mongoose将使用名为_id的字段自动创建userId。因此,创建新的以下文档的最终结果将是:

{
    _id: "klajdsfñalkdjf" //random characters created by mongoose,
    followers: ["adfadf134234", "adfadte345"] //same as before, these are Ids of the users randomly generated by mongoose
    followers: ["adfadf134234", "adfadte345"] 
}

{
 _id: adfadf134234,
 fullName: "alex",
}

现在,因为我们没有用随机数作为跟随对象中跟随对象和跟随者字段中的信息,所以我们现在可以使用可用于文档本身的.populate()方法来将这些ID转换为实际信息。您可以在此处查看有关此内容的更多信息:mongoose documentation

我们的最终结果将是这样的:

{
    _id: "añfakdlsfja",
    followers : [{_id: "adlfadsfj", fullName: "alex"}],
    following : [{_id: "adfadfad" , fullName: "other"}, {_id: "dagadga", fullName: "another"}]
}