मुझे लगता है कि आपको अपने स्कीमा को सरल तरीके से फिर से डिज़ाइन करने की आवश्यकता है, मॉडलों के बीच बहुत सारे संदर्भ हैं, और यह मुद्दों का कारण बनता है, उदाहरण के लिए आपके पास 5 डीबी एक्सेस है जब आप एक टिप्पणी बनाना चाहते हैं, और जब आप चाहते हैं तो 6 डीबी एक्सेस एक टिप्पणी हटाएं।
मैं पोस्ट और टिप्पणी संदर्भों को हटाते हुए इस तरह उपयोगकर्ता स्कीमा बनाउंगा, लेकिन बाद में जब हम उपयोगकर्ताओं से पोस्ट तक पहुंचना चाहते हैं, तो मैंने सेट अप किया आभासी आबादी।
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"
});
और पोस्ट स्कीमा में, मैंने टिप्पणियों के संदर्भ हटा दिए। (सादगी के लिए मैंने पसंद और नापसंद फ़ील्ड हटा दिए।)
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"
});
टिप्पणी स्कीमा जस की तस बनी रह सकती है।
अब किसी पोस्ट में टिप्पणी जोड़ने के लिए, हमें केवल 2 डीबी एक्सेस की आवश्यकता है, एक यह जांचने के लिए कि क्या पोस्ट मौजूद है, और एक पोस्ट बनाने के लिए।
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");
}
}
);
मान लें कि हमारे पास ये 2 उपयोगकर्ता हैं:
{
"_id" : ObjectId("5e216d74e7138b638cac040d"),
"name" : "user1"
}
{
"_id" : ObjectId("5e217192d204a26834d013e8"),
"name" : "user2"
}
User1 _id:"5e216d74e7138b638cac040d"
के साथ यह पोस्ट है।
{
"_id": "5e2170e7d204a26834d013e6",
"user": "5e216d74e7138b638cac040d",
"text": "Post 1",
"date": "2020-01-17T08:31:35.699Z",
"__v": 0,
"id": "5e2170e7d204a26834d013e6"
}
मान लें कि user2 _id:"5e217192d204a26834d013e8"
के साथ है इस पोस्ट पर दो बार इस तरह टिप्पणी की:
{
"_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
}
एक टिप्पणी को हटाने के लिए हम निम्नलिखित मार्ग का उपयोग कर सकते हैं, जैसा कि आप देखते हैं कि हमने डीबी एक्सेस को 6 से घटाकर 3 कर दिया है, और कोड छोटा और साफ है।
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");
}
});
अब आप पूछ सकते हैं कि यूजर के पोस्ट को कैसे एक्सेस किया जाएगा? चूंकि हम अपने उपयोगकर्ता स्कीमा में वर्चुअल पॉप्युलेट सेट करते हैं, हम पोस्ट को इस तरह से पॉप्युलेट कर सकते हैं:
router.get("/users/:id/posts", async (req, res) => {
const result = await User.findById(req.params.id).populate("posts");
res.send(result);
});