Menu

MongoDB مع Node.js: أمثلة find وinsert وupdate

استخدم MongoDB من Node.js عبر برنامج التشغيل الرسمي mongodb: اتصل بـ MongoClient، ثم أضف المستندات وابحث عنها وحدّثها واحذفها في مجموعة، كل ذلك مع async/await.

تحتوي هذه الصفحة على محررات قابلة للتشغيل. حرّر، شغّل، وشاهد النتيجة فوراً.

لاستخدام MongoDB من Node.js، ثبّت برنامج التشغيل الرسمي (npm install mongodb)، واتصل بـ new MongoClient(uri)، واختر قاعدة بيانات بـ client.db('name') ومجموعة بـ db.collection('name'). كل عملية (insertOne وfind وupdateOne وdeleteOne) تعيد وعدًا، فتنتظرها بـ await. تدخل المستندات وتخرج ككائنات JavaScript عادية.

يطبع [ 'Dune', 'Neuromancer', 'Hyperion' ]. لم تكن قاعدة البيانات shop ولا المجموعة books موجودتين من قبل: ينشئهما MongoDB عند أول إضافة، وتحمّل toArray() كل مستند يشير إليه مؤشر find().

البحث عن المستندات مع المرشحات والإسقاط

المرشح (filter) كائن يصف المستندات التي تريدها. القيم العادية تطابق بالضبط؛ والعوامل مثل $gt و$lt و$in و$regex توضع في كائن متداخل. ويختار projection في الوسيط الثاني الحقول التي تعود.

تحمل recent أحدث كتابين بعد 1960، Hyperion ثم Neuromancer، مع title وyear فقط؛ وتعيد findOne أول تطابق (أو null)، وتعدّ countDocuments كتابين، 2، ثمن كل منهما 10 أو أكثر. غيّر $gt: 1960 إلى $gt: 1985 فلا يبقى إلا Hyperion.

التحديث والحذف

تغيّر updateOne(filter, update) أول مستند مطابق. يستخدم التحديث عوامل: $set يستبدل حقولًا، و$inc يضيف إلى رقم، و$unset يحذف حقلًا، و$push يُلحق بمصفوفة. وتعمل updateMany وdeleteMany على كل التطابقات.

طابق التحديث مستندًا واحدًا وعدّله، فصار ثمن Dune الآن 10 والمخزون 2، وحذف الكتاب الذي لا مخزون له يترك 1. يجب أن يستخدم التحديث عوامل: مرّر { price: 10 } دون $set فيرفضه برنامج التشغيل (replaceOne هو الاستدعاء الذي يستبدل مستندًا كاملًا).

ObjectId والفهارس

كل مستند يحصل على _id؛ وحين لا تضبطه بنفسك ينشئ برنامج التشغيل ObjectId. للعثور على مستند بمعرّف وصل كنص (من عنوان URL مثلًا)، غلّفه بـ new ObjectId(id). يجعل الفهرس البحث في حقل سريعًا، ويجعل الفهرس الفريد MongoDB يرفض التكرارات.

يتكوّن ObjectId كنص من 24 محرفًا ست عشريًا، والبحث بالنص العادي لا يجد شيئًا، فيطبع ذلك السطر null. وتخالف الإضافة الثانية الفهرس الفريد فتفشل بالرمز 11000، وهكذا تكتشف أن "البريد مستخدم مسبقًا".

استخدام MongoDB في واجهة API بـ Express

اتصل مرة واحدة حين يبدأ الخادم وشارك المجموعة؛ لا تفتح اتصالًا جديدًا مع كل طلب. يحتفظ برنامج التشغيل بمجموعة من الاتصالات ويعيد استخدامها.

يعيد GET /books الكتابين، لكل منهما _id. انسخ أحد المعرّفات إلى GET /books/<id> لجلب كتاب واحد، أو أرسل POST /books مع جسم JSON مثل {"title": "Foundation", "year": 1951} ثم اسرد الكتب مرة أخرى.

التطبيق الحقيقي يقرأ سلسلة الاتصال من process.env.MONGODB_URI بدلًا من كتابتها في الشيفرة.

إذا أردت مخططات وتحققًا فوق برنامج التشغيل، فإن Mongoose (npm install mongoose) يغلّفه:

const Book = mongoose.model('Book', new mongoose.Schema({ title: String, year: Number }));
await Book.create({ title: 'Dune', year: 1965 });

أخطاء شائعة

نسيان toArray(). تعيد find() مؤشرًا (cursor) لا مستندات. طباعته تُظهر كائن مؤشر؛ استدعِ toArray()، أو مرّ عليه بـ for await.

الاتصال مع كل طلب. كل new MongoClient يفتح مجموعة اتصالات خاصة به. أنشئ عميلًا واحدًا عند بدء التشغيل وأعد استخدامه في كل مكان.

عدم إغلاق العميل أبدًا في سكربت. العميل المفتوح يُبقي العملية حية بعد انتهاء شيفرتك. استدعِ await client.close() في نهاية السكربتات؛ أما الخادم فيُبقيه مفتوحًا طوال عمره.

الأسئلة الشائعة

هل أستخدم برنامج التشغيل mongodb أم Mongoose؟

برنامج التشغيل هو الطبقة الرسمية الأخف: تعمل مع كائنات عادية ولغة الاستعلام الخاصة بـ MongoDB. يضيف Mongoose فوقه المخططات (schemas) والتحقق والنماذج، وهذا يفيد حين تريد فحص كل مستند. كلاهما يتحدث مع قاعدة البيانات نفسها، وMongoose يستخدم برنامج التشغيل في داخله.

هل أحتاج إلى إنشاء قاعدة بيانات أو مجموعة أولًا؟

لا. ينشئ MongoDB كليهما في أول مرة تضيف فيها مستندًا إليهما. أما client.db('shop') وdb.collection('books') فلا تعيدان إلا مقابض.

أين أضع سلسلة الاتصال؟

في متغير بيئة مثل MONGODB_URI، تقرؤه بـ process.env.MONGODB_URI. سلسلة قاعدة البيانات المستضافة تحتوي كلمة مرور، فيجب ألا تُرفع إلى المستودع أبدًا.

لماذا لا تعيد find أي مستندات حين أبحث بالمعرّف؟

يُخزَّن _id على أنه ObjectId لا نص، فلا يطابق { _id: '65f1...' } أي شيء. حوّله أولًا: { _id: new ObjectId(id) }.

رسم توضيحي للغات البرمجة في Coddy

تعلّم البرمجة مع Coddy

ابدأ الآن