Tôi nghĩ bạn cần thiết kế lại lược đồ của mình theo cách đơn giản hơn, có quá nhiều tham chiếu giữa các mô hình và điều này gây ra sự cố, ví dụ:bạn có quyền truy cập 5 db khi muốn tạo nhận xét và truy cập 6 db khi bạn muốn xóa một bình luận.
Tôi sẽ tạo lược đồ người dùng như thế này để xóa các bài đăng và tham chiếu nhận xét, nhưng sau này khi chúng tôi muốn truy cập các bài đăng từ người dùng, tôi đã thiết lập dân số ảo.
const UserSchema = new Schema(
{
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
avatar: {
type: String
},
date: {
type: Date,
default: Date.now
}
},
{
toJSON: { virtuals: true }
}
);
UserSchema.virtual("posts", {
ref: "Post",
localField: "_id",
foreignField: "user"
});
Và trong lược đồ bài đăng, tôi đã xóa các tham chiếu nhận xét. (Để đơn giản hơn, tôi đã xóa các trường thích và không thích.)
const PostSchema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: "User"
},
text: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
},
{
toJSON: { virtuals: true }
}
);
PostSchema.virtual("comments", {
ref: "Comment",
localField: "_id",
foreignField: "post"
});
Lược đồ nhận xét có thể giữ nguyên.
Giờ đây, để thêm nhận xét vào bài đăng, chúng tôi chỉ cần quyền truy cập 2 db, một để kiểm tra xem bài đăng có tồn tại hay không và một để tạo bài đăng.
router.post(
"/comment/:id",
[
auth,
[
check("text", "Text is required")
.not()
.isEmpty()
]
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const post = await Post.findById(req.params.id);
if (!post) {
return res.status(404).json({ msg: "Post not found" });
}
let comment = new Comment({
text: req.body.text,
post: req.params.id,
user: req.user.id
});
comment = await comment.save();
res.json(comment);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
}
);
Giả sử chúng tôi có 2 người dùng sau:
{
"_id" : ObjectId("5e216d74e7138b638cac040d"),
"name" : "user1"
}
{
"_id" : ObjectId("5e217192d204a26834d013e8"),
"name" : "user2"
}
Người dùng1 với _id:"5e216d74e7138b638cac040d"
có bài đăng này.
{
"_id": "5e2170e7d204a26834d013e6",
"user": "5e216d74e7138b638cac040d",
"text": "Post 1",
"date": "2020-01-17T08:31:35.699Z",
"__v": 0,
"id": "5e2170e7d204a26834d013e6"
}
Giả sử user2 với _id:"5e217192d204a26834d013e8"
đã nhận xét về bài đăng này hai lần như thế này:
{
"_id" : ObjectId("5e2172a4957c02689c9840d6"),
"text" : "User2 commented on user1 post1",
"post" : ObjectId("5e2170e7d204a26834d013e6"),
"user" : ObjectId("5e217192d204a26834d013e8"),
"date" : ISODate("2020-01-17T11:39:00.396+03:00"),
"__v" : 0
},
{
"_id": "5e21730d468bbb7ce8060ace",
"text": "User2 commented again on user1 post1",
"post": "5e2170e7d204a26834d013e6",
"user": "5e217192d204a26834d013e8",
"date": "2020-01-17T08:40:45.997Z",
"__v": 0
}
Để xóa nhận xét, chúng tôi có thể sử dụng tuyến sau, như bạn thấy, chúng tôi đã giảm quyền truy cập db từ 6 xuống 3 và mã ngắn hơn và rõ ràng hơn.
router.delete("/comment/:id/:comment_id", auth, async (req, res) => {
try {
const comment = await Comment.findById(req.params.comment_id);
if (!comment) {
return res.status(404).json({ msg: "Post do not have this comment" });
}
if (comment.user.toString() !== req.user.id) {
return res.status(401).json({ msg: "User not authorized" });
}
await comment.remove();
// resend the comments that belongs to that post
const postComments = await Comment.find({ post: req.params.id });
res.json(postComments);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
Bây giờ bạn có thể hỏi, làm thế nào sẽ truy cập các bài viết từ một người dùng? Vì chúng tôi thiết lập dân số ảo trong lược đồ người dùng của mình, chúng tôi có thể điền các bài đăng như sau:
router.get("/users/:id/posts", async (req, res) => {
const result = await User.findById(req.params.id).populate("posts");
res.send(result);
});