ما هي MongoDB؟
MongoDB هي قاعدة بيانات NoSQL من نوع Document-based تخزن البيانات بصيغة JSON-like (BSON). تتميز بالمرونة والسرعة وقابلية التوسع.
لماذا MongoDB؟
- مرنة - لا حاجة لـ Schema ثابت
- سريعة - أداء عالي للقراءة والكتابة
- قابلة للتوسع - Horizontal Scaling
- سهلة التعلم - بنية بسيطة
- متوافقة مع JavaScript
التثبيت والإعداد
1. تثبيت MongoDB
يمكنك استخدام MongoDB Atlas (Cloud) أو تثبيت MongoDB محلياً:
# macOS (باستخدام Homebrew)
brew tap mongodb/brew
brew install mongodb-community
# Ubuntu/Debian
sudo apt install mongodb
# Windows
# حمل من: https://www.mongodb.com/try/download/community
2. تثبيت Mongoose
Mongoose هي مكتبة ODM (Object Document Mapper) لـ MongoDB:
pnpm add mongoose
الاتصال بقاعدة البيانات
const mongoose = require('mongoose');
// Connection String
const DB_URI = 'mongodb://localhost:27017/mydatabase';
// أو MongoDB Atlas:
// const DB_URI = 'mongodb+srv://username:password@cluster.mongodb.net/mydatabase';
// الاتصال بقاعدة البيانات
async function connectDB() {
try {
await mongoose.connect(DB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
console.log('✅ تم الاتصال بـ MongoDB بنجاح');
} catch (err) {
console.error('❌ فشل الاتصال:', err.message);
process.exit(1);
}
}
connectDB();
استخدام متغيرات البيئة
احفظ Connection String في ملف .env بدلاً من كتابتها مباشرة في الكود
تعريف Schema و Model
Schema يحدد بنية المستند، و Model يستخدم للتفاعل مع قاعدة البيانات:
const mongoose = require('mongoose');
// تعريف Schema
const userSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'الاسم مطلوب'],
trim: true,
minlength: 3
},
email: {
type: String,
required: true,
unique: true,
lowercase: true
},
age: {
type: Number,
min: 18,
max: 120
},
isActive: {
type: Boolean,
default: true
},
createdAt: {
type: Date,
default: Date.now
}
});
// إنشاء Model
const User = mongoose.model('User', userSchema);
module.exports = User;
عمليات CRUD
Create - إنشاء مستندات
const User = require('./models/User');
// طريقة 1: إنشاء مستخدم واحد
async function createUser() {
try {
const user = await User.create({
name: 'أحمد محمد',
email: 'ahmed@example.com',
age: 25
});
console.log('تم إنشاء المستخدم:', user);
} catch (err) {
console.error('خطأ:', err.message);
}
}
// طريقة 2: باستخدام new و save()
async function createUserAlt() {
const user = new User({
name: 'فاطمة علي',
email: 'fatima@example.com',
age: 30
});
await user.save();
console.log('تم الحفظ:', user);
}
// طريقة 3: إنشاء عدة مستخدمين
async function createMany() {
const users = await User.insertMany([
{ name: 'محمد', email: 'mohamed@test.com', age: 28 },
{ name: 'سارة', email: 'sara@test.com', age: 24 }
]);
console.log('تم إنشاء ${users.length} مستخدمين');
}
Read - قراءة البيانات
// جلب جميع المستخدمين
const users = await User.find();
// جلب مستخدم واحد
const user = await User.findOne({ email: 'ahmed@example.com' });
// جلب حسب ID
const userById = await User.findById('64a5f8d2e1b2c3d4e5f6g7h8');
// جلب مع شروط
const activeUsers = await User.find({ isActive: true });
const adults = await User.find({ age: { $gte: 18 } });
// جلب مع Projection (تحديد الحقول)
const names = await User.find().select('name email -_id');
// جلب مع Pagination
const page = 1;
const limit = 10;
const skip = (page - 1) * limit;
const paginatedUsers = await User.find()
.skip(skip)
.limit(limit)
.sort({ createdAt: -1 });
// جلب مع Search
const searchResults = await User.find({
name: { $regex: 'أحمد', $options: 'i' }
});
Update - تحديث البيانات
// تحديث مستخدم واحد
const updated = await User.findByIdAndUpdate(
userId,
{ name: 'اسم جديد', age: 26 },
{ new: true, runValidators: true }
);
// تحديث حسب شرط
await User.updateOne(
{ email: 'ahmed@example.com' },
{ $set: { isActive: false } }
);
// تحديث عدة مستندات
await User.updateMany(
{ age: { $lt: 18 } },
{ $set: { isActive: false } }
);
// استخدام Operators
await User.findByIdAndUpdate(userId, {
$inc: { age: 1 }, // زيادة
$push: { tags: 'new' }, // إضافة إلى Array
$pull: { tags: 'old' } // حذف من Array
});
Delete - حذف البيانات
// حذف مستخدم حسب ID
await User.findByIdAndDelete(userId);
// حذف حسب شرط
await User.deleteOne({ email: 'test@example.com' });
// حذف عدة مستندات
await User.deleteMany({ isActive: false });
// حذف جميع المستندات (احذر!)
await User.deleteMany({});
مثال عملي: API كامل
const express = require('express');
const mongoose = require('mongoose');
const User = require('./models/User');
const app = express();
app.use(express.json());
// الاتصال بقاعدة البيانات
mongoose.connect('mongodb://localhost:27017/mydatabase')
.then(() => console.log('✅ MongoDB متصل'))
.catch(err => console.error('❌ خطأ:', err));
// GET - جلب جميع المستخدمين
app.get('/api/users', async (req, res) => {
try {
const users = await User.find();
res.json({
success: true,
count: users.length,
data: users
});
} catch (err) {
res.status(500).json({
success: false,
error: err.message
});
}
});
// GET - جلب مستخدم واحد
app.get('/api/users/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({
success: false,
error: 'المستخدم غير موجود'
});
}
res.json({ success: true, data: user });
} catch (err) {
res.status(500).json({
success: false,
error: err.message
});
}
});
// POST - إنشاء مستخدم
app.post('/api/users', async (req, res) => {
try {
const user = await User.create(req.body);
res.status(201).json({
success: true,
data: user
});
} catch (err) {
res.status(400).json({
success: false,
error: err.message
});
}
});
// PUT - تحديث مستخدم
app.put('/api/users/:id', async (req, res) => {
try {
const user = await User.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true, runValidators: true }
);
if (!user) {
return res.status(404).json({
success: false,
error: 'المستخدم غير موجود'
});
}
res.json({ success: true, data: user });
} catch (err) {
res.status(400).json({
success: false,
error: err.message
});
}
});
// DELETE - حذف مستخدم
app.delete('/api/users/:id', async (req, res) => {
try {
const user = await User.findByIdAndDelete(req.params.id);
if (!user) {
return res.status(404).json({
success: false,
error: 'المستخدم غير موجود'
});
}
res.json({
success: true,
message: 'تم حذف المستخدم'
});
} catch (err) {
res.status(500).json({
success: false,
error: err.message
});
}
});
app.listen(3000, () => {
console.log('API يعمل على المنفذ 3000');
});
أفضل الممارسات
استخدم Indexes
أضف indexes للحقول التي تبحث فيها كثيراً لتحسين الأداء
Validation
استخدم Schema Validation للتأكد من صحة البيانات
معالجة الأخطاء
تعامل مع الأخطاء بشكل صحيح باستخدام try/catch
Connection Pooling
Mongoose تدير Connection Pool تلقائياً