Вы можете упростить свою пользовательскую схему и логику c, чтобы избрать тренинг, удалив лайки из пользовательской модели.
Вот шаги:
1-) Удалить лайки из пользовательской модели
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
name: String,
});
module.exports = mongoose.model("User", UserSchema);
2-) Теперь нам нужно только изменить массив лайков в обучении модель.
exports.favoriteTraining = catchAsync(async (req, res, next) => {
const loggedUserId = req.user.id;
let training = await Training.findById(req.params.id);
const alreadyLiked = training.likes.find((like) => like.toString() === loggedUserId) !== undefined;
if (alreadyLiked) return next(new AppError("Training already liked", 400));
training.likes.push(loggedUserId);
training = await training.save({ validateBeforeSave: false });
res.status(201).json({
status: "success",
data: {
training,
},
});
});
Как вы видите, мы сделали здесь только 2 дБ (было 4). Также я советую использовать push
вместо unshift
, unshift изменяет индекс всех элементов в массиве, pu sh добавляет только новый элемент в конец.
3-) Так как мы удалили лайки от пользователя, нам нужно найти способ ссылки на тренинги от пользователя.
Допустим, мы хотим найти пользователя по идентификатору и получить тренинги, которые он / она предпочитает. Для этого мы можем использовать агрегацию mongodb $ lookup . (Мы могли бы также использовать функцию виртуального заполнения mon goose, но поиск лучше.)
exports.getUserAndFavoritedTrainings = catchAsync(async (req, res, next) => {
const loggedUserId = req.user.id;
const result = await User.aggregate([
{
$match: {
_id: mongoose.Types.ObjectId(loggedUserId),
},
},
{
$lookup: {
from: "trainings", //must be physcial name of the collection
localField: "_id",
foreignField: "likes",
as: "favorites",
},
},
{
$project: {
__v: 0,
"favorites.likes": 0,
"favorites.__v": 0,
},
},
]);
if (result.length > 0) {
return res.send(result[0]);
} else {
return next(new AppError("User not found", 400));
}
});
TEST:
Допустим, у нас есть 2 пользователя:
{
"_id" : ObjectId("5ea7fb904c166d2cc42fd862"),
"name" : "Krzysztof"
},
{
"_id" : ObjectId("5ea808988c6f2207c8289191"),
"name" : "SuleymanSah"
}
И эти два тренинга:
{
"_id" : ObjectId("5ea7fbc34c166d2cc42fd863"),
"likes" : [
ObjectId("5ea7fb904c166d2cc42fd862"), // Swimming favorited by Krzysztof
ObjectId("5ea808988c6f2207c8289191") // Swimming favorited by SuleymanSah
],
"name" : "Swimming Training",
},
{
"_id" : ObjectId("5ea8090d6191c60a00fe9d87"),
"likes" : [
ObjectId("5ea7fb904c166d2cc42fd862") // Running favorited by Krzysztof
],
"name" : "Running Training"
}
Если вошедший в систему пользователь - Кшиштоф, результат будет таким:
{
"_id": "5ea7fb904c166d2cc42fd862",
"name": "Krzysztof",
"favorites": [
{
"_id": "5ea7fbc34c166d2cc42fd863",
"name": "Swimming Training"
},
{
"_id": "5ea8090d6191c60a00fe9d87",
"name": "Running Training"
}
]
}
Вы можете поиграть с этим агрегатом в этом детская площадка