#node.js #mongodb #mongoose
#node.js #mongodb #mongoose
Вопрос:
Я выполняю простую функцию follow friend.
Пожалуйста, смотрите Мои коды ниже:
Следующая схема:
{
"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 подписчика. Интересно, что вызывает эту проблему. Ценю любую помощь. Спасибо!
Ответ №1:
Вы можете попробовать,
$addFields
чтобы создать уникальный массив, вызываемыйuserIds
как массивамиfollowers
, так иfollowings
$setUnion
для получения уникальных идентификаторов,$lookup
с помощью коллекции пользователей$project
для отображения полей,followers
получить полное имя, $map для итерации циклаfollowers
и получить имяfollowerId
из массива пользователей, используя$reduce
и$cond
followings
получить полное имя, $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"
]
}
}
}
}
]
}
}
}
}
}
])
Комментарии:
1. Привет, спасибо за это! У меня есть еще один вопрос. Как мы можем добавить две дополнительные коллекции, такие как изображения и лайки, и отображать изображение пользователя и лайки в массивах подписчиков и подписчиков?
Ответ №2:
при работе с отношениями в Mongoose вы должны создать отношения на основе уникального идентификатора, а затем ссылаться на документ. В вашем случае это было бы:
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 . итак, конечным результатом создания новых следующих документов будет:
{
_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",
}
теперь, поскольку нам не нужно иметь случайное число в качестве информации в полях following и followers в следующем объекте, теперь мы можем использовать метод .populate(), который можно использовать над самим документом для преобразования этих идентификаторов в фактическую информацию. Подробнее об этом здесь: документация mongoose
наш конечный результат будет примерно таким:
{
_id: "añfakdlsfja",
followers : [{_id: "adlfadsfj", fullName: "alex"}],
following : [{_id: "adfadfad" , fullName: "other"}, {_id: "dagadga", fullName: "another"}]
}