MongoDB / Mongoose CRUD
Mongoose CRUD
Mongoose-ийн Model нь MongoDB-ийн бүх CRUD үйлдлийг дэмждэг — гэхдээ driver-аас хялбар, TypeScript-тэй нягт нийцтэй. Энэ хичээлд нийтлэг методуудыг жишээтэйгээр авч үзнэ.
Model.create() — үүсгэх
typescript
import User from "./models/User";
// Нэг document үүсгэх
const user = await User.create({
username: "bold_bataa",
email: "bold@example.com",
xp: 0,
});
console.log(user._id); // ObjectId автоматаар үүссэн
console.log(user.createdAt); // timestamps: true — автоматаар орсон
// Олон document нэгэн зэрэг үүсгэх
const users = await User.create([
{ username: "dorj", email: "dorj@example.com" },
{ username: "od", email: "od@example.com" },
]);
find() — олон document хайх
typescript
// Бүгдийг авах
const allUsers = await User.find();
// Нөхцөлтэй хайх
const activeUsers = await User.find({ role: "user" });
// Projection + sort + limit
const topUsers = await User.find({}, { username: 1, xp: 1 })
.sort({ xp: -1 })
.limit(10);
// $gte, $lt зэрэг operator-ууд ижил хэвээр
const seniorUsers = await User.find({ xp: { $gte: 500 } });
findById() — ID-аар нэг document хайх
typescript
const user = await User.findById("64abc1234567890123456789");
if (!user) {
throw new Error("Хэрэглэгч олдсонгүй");
}
console.log(user.username);
findOne() — нэг document хайх
typescript
// И-мэйлээр хайх
const user = await User.findOne({ email: "bold@example.com" });
// Олдохгүй бол null буцна
if (!user) {
return res.status(404).json({ error: "Хэрэглэгч олдсонгүй" });
}
findByIdAndUpdate() — ID-аар шинэчлэх
typescript
// new: true — шинэчлэгдсэн document-ийг буцаана (анхдагч: хуучин document)
const updated = await User.findByIdAndUpdate(
userId,
{ $inc: { xp: 10 }, $set: { lastActive: new Date() } },
{ new: true, runValidators: true },
);
// runValidators: true — Schema validation-ийг update-д ч ажиллуулна
findByIdAndDelete() — ID-аар устгах
typescript
const deleted = await User.findByIdAndDelete(userId);
if (!deleted) {
throw new Error("Устгах document олдсонгүй");
}
populate() — reference холбох
ref тавигдсан ObjectId талбарыг populate ашиглан бодит document-ээр солино — $lookup-ийн Mongoose хувилбар:
typescript
// Post schema-д authorId: { type: Schema.Types.ObjectId, ref: "User" }
const post = await Post.findById(postId).populate("authorId");
console.log(post.authorId.username); // ObjectId биш — бодит User object
Populate-д projection нэмж болно — хэрэгтэй талбаруудаа л авах:
typescript
const post = await Post.findById(postId).populate(
"authorId",
"username email -_id",
); // зөвхөн username, email
Олон талбарыг populate хийх:
typescript
const post = await Post.findById(postId)
.populate("authorId", "username")
.populate("comments.userId", "username");
Middleware — pre/post hook
Mongoose middleware нь тодорхой үйлдлийн өмнө (pre) эсвэл дараа (post) код ажиллуулдаг.
pre("save") — хадгалахаас өмнө
typescript
import bcrypt from "bcrypt";
// Нууц үг хадгалахаас өмнө hash хийх
userSchema.pre("save", async function (next) {
// Зөвхөн password өөрчлөгдсөн үед hash хий
if (!this.isModified("password")) return next();
this.password = await bcrypt.hash(this.password, 10);
next();
});
post("save") — хадгалсаны дараа
typescript
// Шинэ хэрэглэгч бүртгэгдсэний дараа welcome и-мэйл илгээх
userSchema.post("save", async function (doc) {
await sendWelcomeEmail(doc.email, doc.username);
});
pre("findOneAndDelete") — устгахаас өмнө
typescript
// Хэрэглэгч устгагдахад тухайн хэрэглэгчийн нийтлэлүүдийг ч устгах
userSchema.pre("findOneAndDelete", async function (next) {
const userId = this.getQuery()._id;
await Post.deleteMany({ authorId: userId });
next();
});
Бүрэн жишээ: Express route
typescript
import express from "express";
import User from "../models/User";
import Post from "../models/Post";
const router = express.Router();
// GET /users/:id — хэрэглэгч + нийтлэлүүд
router.get("/:id", async (req, res) => {
try {
const user = await User.findById(req.params.id).select("-password"); // password хасах
if (!user) {
return res.status(404).json({ error: "Хэрэглэгч олдсонгүй" });
}
const posts = await Post.find({ authorId: user._id })
.sort({ createdAt: -1 })
.limit(5)
.select("title createdAt");
res.json({ user, recentPosts: posts });
} catch (error) {
res.status(500).json({ error: "Серверийн алдаа" });
}
});
// PATCH /users/:id/xp — XP нэмэх
router.patch("/:id/xp", async (req, res) => {
const user = await User.findByIdAndUpdate(
req.params.id,
{ $inc: { xp: 10 } },
{ new: true },
);
res.json({ xp: user?.xp, level: user?.level });
});
export default router;
Дараагийн хичээлд:
MongoDB болон Mongoose-ийг production-д ашиглахад мөрдөх шилдэг туршлагуудыг үзнэ.