<?xml version="1.0"?>
<rss version="2.0"><channel><title>DevOps: MongoDB</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/?d=4</link><description>DevOps: MongoDB</description><language>ar</language><item><title>&#x637;&#x631;&#x642; &#x627;&#x644;&#x627;&#x62A;&#x635;&#x627;&#x644; &#x628;&#x62E;&#x627;&#x62F;&#x645; MongoDB</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/%D8%B7%D8%B1%D9%82-%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%A8%D8%AE%D8%A7%D8%AF%D9%85-mongodb-r850/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_05/---MongoDB.png.552b184eb3dbfc1104fde9194c8dccd1.png" /></p>
<p>
	سنناقش بهذا المقال الخيارات المتنوعة للاتصال بخادم MongoDB، سواءً كان يتضمن قاعدة بيانات وحيدة، أو عدة قواعد بيانات تتمتع كل منها بمَنْفَذٍ خاص. سنعرض أيضًا طريقة الاتصال مع خوادم تعمل على أجهزة متعددة ضمن أمر اتصال واحد، لكن البداية ستكون من تشغيل خادم MongoDB.
</p>

<h2 id="mongodb">
	تشغيل خادم MongoDB
</h2>

<p>
	يمكن تشغيل خادم MongoDB من الملف التنفيذي <code>mongod</code> الموجود في المجلد <code>bin</code> ضمن المجلد الخاص بملفات برنامج MongoDB، حيث بعد تنفيذ الأمر <code>mongod</code>، لن تظهر أي معلومات جديدة على شاشة موجه الأوامر لبعض الوقت حتى يتأسس الاتصال مع خادم MongoDB. وبمجرد إنشاء الاتصال، سيبدأ سجل معلومات الخادم بالظهور.
</p>

<p>
	يمكن الاتصال مع خادم MongoDB بواسطة الصدفة MongoDB Shell، وعند بدء التشغيل سيكون المنفذ 27017 هو المنفذ الافتراضي للاتصال بخادم MongoDB؛ أما إذا أردنا الوصول إلى الخادم من واجهة الويب فيمكننا ذلك باستخدام المنفذ الناتج عن إضافة 1000 إلى رقم منفذ بدء التشغيل، فنكتب عندها الرابط <code><a href="http://localhost:28017" ipsnoembed="true" rel="external nofollow">http://localhost:28017</a></code> في متصفحنا.
</p>

<h2 id="mongodbshell">
	الاتصال بخادم MongoDB من الصدفة Shell
</h2>

<p>
	يبين السطر أبسط صيغة لكتابة أمر الاتصال مع <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r574/" rel="">خادم</a> MongoDB بعد أن شغلناه، علمًا أننا اكتفينا بخيار واحد فقط من خيارات الاتصال المتعددة، وهو خيار لا غنى عنه؛ إذ إنه يشير إلى اسم الحاسوب المضيف hostname، وهو في حالتنا <code>localhost</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_4000_6" style=""><span class="pln">mongodb</span><span class="pun">:</span><span class="com">//localhost</span></pre>

<p>
	وبمجرد تنفيذ الأمر سنحصل على الخرج التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172761" href="https://academy.hsoub.com/uploads/monthly_2025_05/img01-mongodb-connect.png.431ffc56ff326794093295333ac114f8.png" rel=""><img alt="img01 mongodb connect" class="ipsImage ipsImage_thumbnailed" data-fileid="172761" data-unique="zfofppv18" src="https://academy.hsoub.com/uploads/monthly_2025_05/img01-mongodb-connect.png.431ffc56ff326794093295333ac114f8.png"> </a>
</p>

<p>
	إذا عُدنا الآن إلى نافذة موجه الأوامر التي شغلنا فيها خادم MongoDB، وهو نفسه الملف التنفيذي <code>mongod</code>، سنجد أنها تتضمن خرجًا يشبه التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172758" href="https://academy.hsoub.com/uploads/monthly_2025_05/img02-mongodb-server.png.8b214e5c69ef250613308f01745b3b08.png" rel=""><img alt="img02 mongodb server" class="ipsImage ipsImage_thumbnailed" data-fileid="172758" data-unique="w8k4954r1" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_05/img02-mongodb-server.png.8b214e5c69ef250613308f01745b3b08.png"> </a>
</p>

<p>
	يمكننا ملاحظة السطر الأخير، فهو يشير إلى إنشاء اتصال جديد مع خادم MongoDB ويتضمن معلومات عن الجهة المتصلة.
</p>

<p>
	ملاحظة: سيظهر هذا السطر عندما ينجح اتصالنا مع الخادم
</p>

<h2 id="mongodb-1">
	صيغ متنوعة لأمر الاتصال مع خادم MongoDB
</h2>

<p>
	يمكن ذكر الصيغ الآتية لأوامر الاتصال مع خادم MongoDB
</p>

<h3 id="">
	الاتصال بقاعدة البيانات الافتراضية باستخدام اسم مستخدم وكلمة مرور
</h3>

<p>
	يمكننا الاتصال مع خادم MongoDB بواسطة اسم مستخدم وكلمة مرور محددين وفق الصيغة العامة <code>username@hostname/dbname</code>، بحيث نعدل اسم المستخدم username إلى اسم المستخدم الذي نود الاتصال بواسطته مع كلمة المرور الخاصة به، كما نبدل اسم الحاسوب المضيف hostname إلى اسم الحاسوب المضيف الفعلي، و dbname إلى اسم قاعدة البيانات؛ وإذا أردنا الاتصال بقاعدة البيانات الافتراضية، يكفي أن نترك اسم <a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">قاعدة البيانات</a> فارغ، كما هو الحال في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_4000_8" style=""><span class="pln">mongodb</span><span class="pun">:</span><span class="com">//mongo_admin:AxB6_w3r@localhost/</span></pre>

<p>
	ولتوضيح الشيفرة أعلاه، يشير mongo_admin إلى اسم المستخدم، و AxB6_w3r إلى كلمة المرور الخاصة به؛ وهو يحاول الاتصال بقاعدة البيانات الافتراضية الموجودة على الحاسوب المحلي <code>localhost</code>.
</p>

<p>
	وسيكون الخرج كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172760" href="https://academy.hsoub.com/uploads/monthly_2025_05/img03-mongodb-connect-to-default-database.png.57a75cc325e5e98392e48f1a00af5c99.png" rel=""><img alt="img03 mongodb connect to default database" class="ipsImage ipsImage_thumbnailed" data-fileid="172760" data-unique="yx1fj9ujc" src="https://academy.hsoub.com/uploads/monthly_2025_05/img03-mongodb-connect-to-default-database.png.57a75cc325e5e98392e48f1a00af5c99.png"> </a>
</p>

<h3 id="-1">
	الاتصال بقاعدة بيانات معينة باستخدام اسم مستخدم وكلمة مرور
</h3>

<p>
	سنستخدم الصيغة العامة السابقة نفسها <code>username@hostname/dbname</code> مع تعديل كلمة dbname إلى اسم قاعدة البيانات التي نريد بالاتصال بها، وفق التالي:
</p>

<pre class="ipsCode">mongodb://mongo_admin:AxB6_w3r@localhost/w3r
</pre>

<p>
	وباستخدام هذا الأمر سيتصل المستخدم mongo_admin صاحب كلمة المرور AxB6_w3r بقاعدة البيانات w3r الموجودة على الحاسوب المحلي، وسيكون الخرج كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172762" href="https://academy.hsoub.com/uploads/monthly_2025_05/img04-mongodb-connect-with-username-and-password.png.5918bde7294820fb8bdbf5b1dab535fc.png" rel=""><img alt="img04 mongodb connect with username and password" class="ipsImage ipsImage_thumbnailed" data-fileid="172762" data-unique="mgsx8eobj" style="width: 354px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_05/img04-mongodb-connect-with-username-and-password.png.5918bde7294820fb8bdbf5b1dab535fc.png"> </a>
</p>

<p>
	وتجدر الإشارة هنا إلى أننا تستطيع الاتصال بأكثر من مُضيف hostname ضمن أمر اتصال واحد.
</p>

<h3 id="-2">
	الاتصال بقاعدة بيانات معينة باستخدام اسم مستخدم وكلمة مرور ومَنفَذ معين
</h3>

<p>
	يجري هذا الاتصال بطريقة مشابهة للسابق، بحيث نستخدم الصيغة <code>username@hostname/dbname</code> ونضع اسم المستخدم وكلمة المرور؛ وبدلًا من dbname، نكتب اسم قاعدة البيانات التي نريد الاتصال بها، يتبعها رقم المَنفَذ port الذي حددناه للاتصال معها، كما هو الحال في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_4000_11" style=""><span class="pln">mongodb</span><span class="pun">:</span><span class="com">//mongo_admin:AxB6_w3r@localhost/w3r:29000</span></pre>

<p>
	بمعنى أن المستخدم mongo_admin الذي كلمة مروره AxB6_w3r سيحاول الاتصال بقاعدة البيانات w3r الموجودة على الحاسوب المحلي، وذلك عبر المنفذ 29000. وفي الحالات التي لا نذكر فيها رقم منفذ محدد، سيجري الاتصال عبر المنفذ الافتراضي 27107، بحيث سيكون خرج الأمر كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172759" href="https://academy.hsoub.com/uploads/monthly_2025_05/img05-mongodb-connect-to-database-specific-port.png.bccd98a682d6d8e6b27219cb7c2d9bbb.png" rel=""><img alt="img05 mongodb connect to database specific port" class="ipsImage ipsImage_thumbnailed" data-fileid="172759" data-unique="uom7vmrot" src="https://academy.hsoub.com/uploads/monthly_2025_05/img05-mongodb-connect-to-database-specific-port.png.bccd98a682d6d8e6b27219cb7c2d9bbb.png"> </a>
</p>

<h3 id="mongodb-2">
	الاتصال بخوادم MongoDB متعددة تعمل على أجهزة متعددة
</h3>

<p>
	تعمل حالة الاتصال بخوادم MongoDB على أجهزة متعددة عند استخدام مجموعات النسخ المتماثلة replica sets، التي تتألف من عدة عقد تُعدّ نسخًا متطابقة عن بعضها؛ إذ تكتشف المجموعة العقدة الرئيسية Master node تلقائيًا وفي حال فشلت، فإن العقد الثانوية تنوب عنها، وتساعدنا على استرداد النظام من حالات الفشل.
</p>

<p>
	في المثال التالي صيغة الأمر المناسب لهذا النوع من الاتصال:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_4000_13" style=""><span class="pln">mongodb</span><span class="pun">:</span><span class="com">//example_host1.com:27017,example_host2.com:27017</span></pre>

<h3 id="mongodb-3">
	الاتصال بخوادم MongoDB متعددة تعمل على الجهاز نفسه ولكل منها منفذ خاص
</h3>

<p>
	سنستخدم الأمر التالي للاتصال بخوادم MongoDB المتعددة التي تعمل على الجهاز نفسه، لكن على منافذ ports مختلفة. سيفيدنا هذا أيضًا في مجموعات النسخ المتماثلة replica sets:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_4000_15" style=""><span class="pln">mongodb</span><span class="pun">:</span><span class="com">//example_host1.com:27110,example_host1.com:27111</span></pre>

<h3 id="-3">
	الخيارات المرتبطة بالصيغ السابقة
</h3>

<p>
	يبين الجدول التالي الخيارات التي يمكننا استخدامها مع صيغ أوامر الاتصال السابقة:
</p>

<table>
	<thead>
		<tr>
			<th>
				الخيار Option
			</th>
			<th>
				الوصف
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				<code>replicaSet=name</code>
			</td>
			<td>
				عند العمل مع أي لغة برمجة يدعمها MongoDB فإن مُشَغِّل driver لهذه اللغة سيستخدم اسم مجموعة النسخ المتماثلة ليعرف العقد التي تنتمي إليها؛ علمًا أن مُشَغِّل لغة البرمجة أو driver هو جزء التعليمات البرمجية المسؤول عن الاتصال بين لغة برمجة التطبيق ونظام MongoDB.
			</td>
		</tr>
		<tr>
			<td>
				<code>slaveOk=true|false‎</code>
			</td>
			<td>
				يستخدم هذا الخيار للتعامل مع حالتي الكتابة والقراءة في أنظمة النسخ المتماثلة ذات الخوادم المتعددة، فعند الكتابة تُرسل البيانات إلى الخادم الرئيسي primary وعند القراءة تُرسل البيانات إلى جميع الخوادم الاحتياطية أو الثانوية slaves.
			</td>
		</tr>
		<tr>
			<td>
				<code>safe=true|false</code>
			</td>
			<td>
				إذا كانت قيمة <code>safe</code> هي <code>true</code>، فإن مُشَغِّل لغة البرمجة سيُرسل الأمر <code>getLastError</code> بعد تحديث للبيانات ليتأكد من إتمامه بدون أخطاء؛ أما إذا كانت قيمته <code>false</code>، فلن يُرسل المشغل <code>getLastError</code> بعد التحديثات.
			</td>
		</tr>
		<tr>
			<td>
				<code>w=n</code>
			</td>
			<td>
				يُضاف <code>{ w : n }</code> إلى الأمر <code>getLastError</code> الذي يرسله مُشَغِّل لغة البرمجة، وهو يفرض بطبيعة الحال إسناد القيمة <code>true</code> للخيار <code>safe=true</code>.
			</td>
		</tr>
		<tr>
			<td>
				<code>wtimeoutMS=ms</code>
			</td>
			<td>
				يُضاف <code>{ wtimeout : ms }</code> إلى الأمر <code>getLastError</code> الذي يرسله مُشَغِّل لغة البرمجة، وهو يعني حكمًا أن <code>safe=true</code>.
			</td>
		</tr>
		<tr>
			<td>
				<code>fsync=true|false</code>
			</td>
			<td>
				إذا كانت قيمة هذا الخيار هي <code>true</code>، فسيُضاف الخيار <code>{ wtimeout : ms }</code> إلى الأمر <code>getLastError</code> الذي يُرسله مُشَغِّل لغة البرمجة، وهذا يفرض بالطبع أن تكون <code>safe=true</code>؛ أما إذا أعطينا <code>fsync</code> القيمة <code>false</code>، فإن الأمر <code>getLastError</code> لن يُرسل أبدًا.
			</td>
		</tr>
		<tr>
			<td>
				<code>journal=true|false</code>
			</td>
			<td>
				إذا أُعطيت القيمة <code>true</code> لهذا الخيار فستجري مزامنة مع يومية قاعدة البيانات journal التي تتضمن عادةً إدخالات قاعدة البيانات التي لم تُثَبَّت بعد uncommitted، وهذه الحالة تفرض دائمًا إسناد القيمة <code>true</code> للخيار <code>safe=true</code>.
			</td>
		</tr>
		<tr>
			<td>
				<code>connectTimeoutMS=ms</code>
			</td>
			<td>
				يُحدد الزمن الأقصى لمحاولة الاتصال مع خادم MongoDB قبل تصنيفه على أنه اتصال غير ممكن.
			</td>
		</tr>
		<tr>
			<td>
				<code>socketTimeoutMS=ms</code>
			</td>
			<td>
				يحدد الزمن الأقصى لمحاولة الإرسال أو الاستقبال على مِقبس التوصيل socket قبل إنهاء المحاولة.
			</td>
		</tr>
	</tbody>
</table>

<h2 id="-4">
	خاتمة
</h2>

<p>
	تعرفنا في هذا المقال على الطرق المتنوعة للاتصال مع خادم MongoDB عبر الصدفة mongo shell. وسواءٌ كان ذلك على مُضيف واحد أو على مضيفين متعددين، يرتكز الاتصال على تحديد أربع أمور أساسية هي بيانات المستخدم الذي سيُنجِز الاتصال، واسم قاعدة البيانات، والمَنْفَذ الخاص بها، واسم المُضيف؛ ويمكننا استخدام الخيارات التي عرضناها في الجدول حسب ما تقتضيه طبيعة مشروعنا.
</p>

<p>
	ترجمة -وبتصرف- لمقال <a href="https://www.w3resource.com/mongodb/connections.php" rel="external nofollow">MongoDB connections</a> من موقع w3resource.
</p>

<h2 id="-5">
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D8%B7%D8%B1%D9%8A%D9%82%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-mongodb-%D8%B9%D9%84%D9%89-%D9%88%D9%8A%D9%86%D8%AF%D9%88%D8%B2-%D9%88%D9%84%D9%8A%D9%86%D9%83%D8%B3-r849/" rel="">طريقة تثبيت MongoDB على ويندوز ولينكس</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%AA%D8%A3%D9%85%D9%8A%D9%86-mongodb-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r435/" rel="">كيفية تثبيت وتأمين MongoDB على أوبونتو 18.04</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r276/" rel="">كيفية إنشاء واستخدام النسخ الاحتياطي لقواعد بيانات MongoDB على نظام أوبنتو</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">دليلك الشامل إلى قواعد البيانات DataBase</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">850</guid><pubDate>Fri, 15 Aug 2025 16:06:02 +0000</pubDate></item><item><title>&#x637;&#x631;&#x64A;&#x642;&#x629; &#x62A;&#x62B;&#x628;&#x64A;&#x62A; MongoDB &#x639;&#x644;&#x649; &#x648;&#x64A;&#x646;&#x62F;&#x648;&#x632; &#x648;&#x644;&#x64A;&#x646;&#x643;&#x633;</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/%D8%B7%D8%B1%D9%8A%D9%82%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-mongodb-%D8%B9%D9%84%D9%89-%D9%88%D9%8A%D9%86%D8%AF%D9%88%D8%B2-%D9%88%D9%84%D9%8A%D9%86%D9%83%D8%B3-r849/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_05/-MongoDB---.png.fca1ff49337653133d51d4230891068b.png" /></p>
<p>
	سنعرض في هذا المقال طريقة تثبيت MongoDB على نظامي تشغيل ويندوز ولينكس، مع تمهيد بسيط لبدء العمل مع الصدفة mongo shell التي تمكننا من التفاعل مع قاعدة البيانات.
</p>

<blockquote class="ipsQuote" data-gramm="false" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		<strong>ملاحظة</strong>: تنطبق الخطوات الواردة هنا على نظامي التشغيل ويندوز ولينكس ما لم يُذكر خلاف ذلك وحتى عندما تكون الصور التوضيحية من أحد النظامين فقط.
	</p>
</blockquote>

<h2 id="download">
	التحميل Download
</h2>

<p>
	يمكن تحميل ذ الثنائية المُعدّة مسبقًا Pre-built binary packages مباشرةً من <a href="https://www.mongodb.com/download-center" rel="external nofollow">موقعها الرسمي</a>، لذا ما علينا سوى اختيار النسخة المناسبة ورقم الإصدار، ونظام التشغيل ويندوز أم <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D9%84%D9%8A%D9%86%D9%83%D8%B3-linux-%D9%88%D8%A3%D8%A8%D8%B1%D8%B2-%D9%85%D9%85%D9%8A%D8%B2%D8%A7%D8%AA%D9%87-%D9%88%D8%B9%D9%8A%D9%88%D8%A8%D9%87-r2252/" rel="">لينكس</a>، ونوعه 32 بت أم 64 بت؛ وعند انتهاء التحميل سيكون من السهل تثبيتها كما سنعرض في الفقرات التالية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172754" href="https://academy.hsoub.com/uploads/monthly_2025_05/img01-mongodb-download.png.9eee2c622034f6323fa0b54f44d4d9d4.png" rel=""><img alt="img01 mongodb download" class="ipsImage ipsImage_thumbnailed" data-fileid="172754" data-unique="utwr0x8w7" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_05/img01-mongodb-download.thumb.png.999ce3ccd43b071005988c831baade1e.png"> </a>
</p>

<h2 id="unzip">
	فك الضغط Unzip
</h2>

<p>
	الخطوة التالية بعد تحميل حزمة MongoDB هي فك ضغطها إلى المجلد المراد تثبيت MongoDB ضمنه؛ وهنا سننشئ مجلدًا خاصًا لهذا الغرض، وسيكون اسمه في مثالنا هو <code>mongodb</code>.
</p>

<h2 id="mongodb">
	إنشاء مجلد بيانات MongoDB
</h2>

<p>
	سننشئ أيضًا مجلدًا خاصًا بالبيانات نسميه <code>data</code>، ثم ننشئ بداخله مجلدًا آخر يسمى <code>db</code>، وهذا هو الاسم الافتراضي للمجلد الذي تخزن فيه MongoDB البيانات، ولأن هذا المجلد لا ينشأ تلقائيًا عند تثبيت MongoDB، فقد أنشأناه يدويًا.
</p>

<p>
	ينبغي إنشاء المجلد <code>data</code> على الجذر مباشرةً، أي على (<code>\:C</code> أو <code>\:D</code> أو نحو ذلك) في ويندوز، وعلى (<code>/</code>) في لينكس، كما يلي:
</p>

<p>
	إنشاء المجلدات في ويندوز (أنشأنا المجلدات على القرص <code>\:D</code> في مثالنا):
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172752" href="https://academy.hsoub.com/uploads/monthly_2025_05/img02-mongodb-installation-windows.png.7d5ee4326eed5fb557bb2f58aafe15f5.png" rel=""><img alt="img02 mongodb installation windows" class="ipsImage ipsImage_thumbnailed" data-fileid="172752" data-unique="xecx4yhiq" src="https://academy.hsoub.com/uploads/monthly_2025_05/img02-mongodb-installation-windows.png.7d5ee4326eed5fb557bb2f58aafe15f5.png"> </a>
</p>

<p>
	إنشاء المجلدات في لينكس:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172755" href="https://academy.hsoub.com/uploads/monthly_2025_05/img03-mongodb-installation-Linux.png.15aef0ae2aa0f1392ebf1dae34fab11a.png" rel=""><img alt="img03 mongodb installation linux" class="ipsImage ipsImage_thumbnailed" data-fileid="172755" data-unique="uelp20tjd" src="https://academy.hsoub.com/uploads/monthly_2025_05/img03-mongodb-installation-Linux.png.15aef0ae2aa0f1392ebf1dae34fab11a.png"> </a>
</p>

<p>
	يمكن إنشاء المجلدات في كلا النظامين من الواجهة الرسومية ومستعرض الملفات في حال الرغبة بذلك من دون الحاجة لموجه الأوامر.
</p>

<h2 id="mongodb-1">
	تشغيل خادم MongoDB من موجه الأوامر
</h2>

<p>
	لتشغيل خادم MongoDB من موجه الأوامر، لا بد من فتح المجلد <code>mongodb</code> الذي أجرينا فيه عملية فك الضغط سابقًا، ثم نفتح المجلد الفرعي ضمنه <code>bin</code>، ونشَغِّل الملف التنفيذي <code>mongod.exe</code>.
</p>

<h2 id="mongodb-2">
	تشغيل خادم MongoDB كخدمة ويندوز
</h2>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<blockquote class="ipsQuote" data-gramm="false" data-ipsquote="">
		<div class="ipsQuote_citation">
			اقتباس
		</div>

		<p>
			هذه الفقرة خاصة بنظام ويندوز فقط.
		</p>
	</blockquote>
</blockquote>

<p>
	سنحتاج لتنفيذ الأمر التالي بصلاحيات مدير نظام administrator لتشغيل خادم MongoDB كخدمة ويندوز:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5504_7" style=""><span class="pln">mongod </span><span class="pun">--</span><span class="pln">bind_ip  yourIPadress  </span><span class="pun">--</span><span class="pln">logpath  </span><span class="str">"C:\data\dbConf\mongodb.log"</span><span class="pln">  </span><span class="pun">--</span><span class="pln">logappend  </span><span class="pun">--</span><span class="pln">dbpath  </span><span class="str">"C:\data\db"</span><span class="pln">  </span><span class="pun">--</span><span class="pln">port yourPortNumber </span><span class="pun">--</span><span class="pln">serviceName </span><span class="str">"YourServiceName"</span><span class="pln"> </span><span class="pun">--</span><span class="pln">serviceDisplayName </span><span class="str">"YourServiceName"</span><span class="pln"> </span><span class="pun">--</span><span class="pln">install</span></pre>

<p>
	لا ننسَ ضبط قيم الوسطاء Arguments ضمن الأمر بما يناسب حالتنا كما هو موضح في الجدول التالي:
</p>

<table>
	<thead>
		<tr>
			<th>
				الوسيط Argument
			</th>
			<th>
				الوصف
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				‎--bind_ip
			</td>
			<td>
				يُكتب بعده عنوان IP الخاص بالحاسوب الذي نستخدمه
			</td>
		</tr>
		<tr>
			<td>
				‎--logpath
			</td>
			<td>
				يليه مسار تخزين ملف تسجيل الأحداث logfile لخادم MongoDB
			</td>
		</tr>
		<tr>
			<td>
				‎--logappend
			</td>
			<td>
				يُفَعِّل هذا الوسيط كتابة سجلات الأحداث logs التي تتولد ضمن ملف تسجيل الأحداث logfile الذي حددناه بالوسيط السابق
			</td>
		</tr>
		<tr>
			<td>
				‎--dbpath
			</td>
			<td>
				يُحَدَّدْ بعده مسار وجود المجلد <code>db</code> ضمن المجلد <code>data</code>
			</td>
		</tr>
		<tr>
			<td>
				‎--port
			</td>
			<td>
				يُكتب بعده المنفذ port الذي خصصناه لخادم MongoDB، وإذا لم نضع أي قيمة هنا، فإن MongoDB سيستخدم المنفذ الافتراضي وهو 20127
			</td>
		</tr>
		<tr>
			<td>
				‎--serviceName
			</td>
			<td>
				يوضع بعده اسم خدمة MongoDB الذي اخترناه
			</td>
		</tr>
		<tr>
			<td>
				‎--serviceDisplayName
			</td>
			<td>
				يُكتب بعده اسم عرض الخدمة أو اسم الإظهار، فلكل خدمة ويندوز اسمين، ويكون هذا الاسم عادةً أوضح ويعبر أكثر عن طبيعة الخدمة. تتضح فائدة هذا الوسيط عندما يكون لدينا أكثر من خدمة MongoDB مُشغلة على نفس الحاسب
			</td>
		</tr>
		<tr>
			<td>
				install--
			</td>
			<td>
				يشير هذا الوسيط إلى أمر تثبيت أو إنشاء MongoDB كخدمة من خدمات ويندوز
			</td>
		</tr>
	</tbody>
</table>

<h2 id="shellmongodb">
	تمهيد لاستخدام الصدفة Shell الخاصة بنظام MongoDB
</h2>

<p>
	لا بد لنا من الحرص على العمل من مستخدم يملك صلاحيات مدير نظام، ثم نشَغَّل الملف التنفيذي <code>mongo.exe</code> الموجود ضمن المجلد <code>bin</code>، أحد المجلدات الفرعية للمجلد الذي ثَبَّتنا فيه MongoDB، وبمجرد تشغيله ستفتح أمامنا الصدفة shell الخاصة بإدارة نظام MongoDB، وهي من نوع JavaScript shell، كما في الصورة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172756" href="https://academy.hsoub.com/uploads/monthly_2025_05/img04-run-mongo-shell.png.94bfd97f59d74225df93bca930ed0084.png" rel=""><img alt="img04 run mongo shell" class="ipsImage ipsImage_thumbnailed" data-fileid="172756" data-unique="5js4b2ldo" src="https://academy.hsoub.com/uploads/monthly_2025_05/img04-run-mongo-shell.png.94bfd97f59d74225df93bca930ed0084.png"> </a>
</p>

<p>
	يمكننا ملاحظة أن MongoDB قد اتصل مباشرةً بقاعدة بيانات مستندية document database تجريبية تدعى test.
</p>

<p>
	يوفر MongoDB لمستخدميه إمكانية الاتصال المباشر بهذا المستند التجريبي أو قاعدة البيانات التجريبية بعد التثبيت.
</p>

<p>
	سنجري الآن بعض العمليات البسيطة لاختبار الصدفة shell، ونكتب مثلًا عمليةً حسابيةً طالما أن الصدفة مكتوبة <a href="https://academy.hsoub.com/programming/javascript/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r1689/" rel="">بلغة JavaScript</a>، ويمكن أيضًا استخدام الأمر <code>db</code> فهو يعطينا اسم قاعدة البيانات المتصل بها:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172753" href="https://academy.hsoub.com/uploads/monthly_2025_05/img05-mongo-shell-exampel.png.abad8f290af60be8bf3dadc14aed15a5.png" rel=""><img alt="img05 mongo shell exampel" class="ipsImage ipsImage_thumbnailed" data-fileid="172753" data-unique="m26152bxp" src="https://academy.hsoub.com/uploads/monthly_2025_05/img05-mongo-shell-exampel.png.abad8f290af60be8bf3dadc14aed15a5.png"> </a>
</p>

<p>
	لنجرب الآن إدخال سجل بسيط وإرجاع بعض المعلومات منه:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="172757" href="https://academy.hsoub.com/uploads/monthly_2025_05/img06-mongo-insert-find.png.faa0c79a13a1ae4fddf4506f56622b96.png" rel=""><img alt="img06 mongo insert find" class="ipsImage ipsImage_thumbnailed" data-fileid="172757" data-unique="nwhnnkeso" style="width: 374px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_05/img06-mongo-insert-find.png.faa0c79a13a1ae4fddf4506f56622b96.png"> </a>
</p>

<p>
	أدخلنا في السطر الأول القيمة 8 إلى الحقل z التابع للمجموعة w3r، ثم استعلمنا عن البيانات؛ علمًا أن المجموعات collections في MongoDB تكافئ الجداول في <a href="https://academy.hsoub.com/programming/sql/%D9%81%D9%87%D9%85-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%B9%D9%84%D8%A7%D9%82%D9%8A%D8%A9-r2216/" rel="">قواعد البيانات العلائقية</a>.
</p>

<h2 id="mongodb-3">
	واجهة الويب لنظام MongoDB
</h2>

<p>
	يمكن الوصول إلى واجهة الويب الخاصة بإدارة MongoDB ومراقبته عبر منفذٍ port خاص، يكون رقمه هو نفسه رقم المنفذ المخصص لخادم MongoDB مضافًا إليه 1000.
</p>

<p>
	فعلى سبيل المثال، إذا كنا نستخدم المنفذ الافتراضي لخادم MongoDB وهو 27017 فمعنى ذلك أنه يمكن الوصول إلى واجهة الويب من المنفذ 28017.
</p>

<h2 id="">
	الخاتمة
</h2>

<p>
	اطلعنا في هذا المقال على خطوات تثبيت MongoDB على نظامي تشغيل ويندوز ولينكس وهي خطوات بسيطة ومتشابهة، ثم تعرفنا على أمر تشغيل خادم MongoDB كخدمة ويندوز وطريقة تعديله ليناسب بيئتك، ووضحنا آلية التعامل مع صفة MongoDB.
</p>

<p>
	ترجمة -وبتصرف- لمقال <a href="https://www.w3resource.com/mongodb/installation-windows.php" rel="external nofollow">Install MongoDB on Windows</a> ومقال <a href="https://www.w3resource.com/mongodb/installation-Linux.php" rel="external nofollow">Install MongoDB on Linux</a> من موقع w3resource.
</p>

<h2 id="-1">
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%AA%D8%A3%D9%85%D9%8A%D9%86-mongodb-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r435/" rel="">كيفية تثبيت وتأمين MongoDB على أوبونتو 18.04</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r276/" rel="">كيفية إنشاء واستخدام النسخ الاحتياطي لقواعد بيانات MongoDB على نظام أوبنتو</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">دليلك الشامل إلى قواعد البيانات DataBase</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">849</guid><pubDate>Wed, 23 Jul 2025 16:06:01 +0000</pubDate></item><item><title>&#x62A;&#x646;&#x641;&#x64A;&#x630; &#x639;&#x645;&#x644;&#x64A;&#x627;&#x62A; CRUD &#x641;&#x64A; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MongoDB</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/%D8%AA%D9%86%D9%81%D9%8A%D8%B0-%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-crud-%D9%81%D9%8A-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-r842/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_04/--CRUD----MongoDB.png.7ba805bbce58cc8919061f68f2492cf8.png" /></p>
<p>
	نشرح في هذه المقالة طريقة التعامل مع نظام إدارة قواعد البيانات MongoDB الذي يمتاز بكونه نظام غير علاقي وموجه نحو المستندات document-oriented، أي أنه يخزن البيانات في هيئة مستندات، ومثله مثل بقية أنظمة إدارة قواعد البيانات فهو يتعامل مع البيانات عبر أربع عمليات أساسية نسميها اختصارًا عمليات CRUD تشمل:
</p>

<ul>
	<li>
		عمليات الإنشاء Create أي كتابة بيانات جديدة لقاعدة البيانات
	</li>
	<li>
		عمليات القراءة Read‎ وهي عمليات الاستعلام التي نحصل بواسطتها على البيانات المخزنة
	</li>
	<li>
		عمليات التحديث Update وتعني العمليات التي تسبب تغييرًا في البيانات الموجودة ضمن قاعدة البيانات
	</li>
	<li>
		عمليات الحذف Delete وهي العمليات التي تؤدي إلى إزالة البيانات نهائيًا من قاعدة البيانات
	</li>
</ul>

<p>
	لنوضح من خلال الأمثلة العملية طريقة تنفيذ هذه كل من هذه العمليات على قاعدة بيانات من نوع MongoDB.
</p>

<h2 id="">
	متطلبات العمل
</h2>

<p>
	لمتابعة سير العمل في هذا المقال يتوجب امتلاك معرفة أساسية بكيفية استخدام واجهة أوامر Mongodb المعروفة باسم Mongodb Shell وتنفيذ أوامر قاعدة البيانات.كما يجب توفّر خادم يعمل بنظام Ubuntu يحتوي على مستخدم عادي غير الجذر يمتلك صلاحيات sudo، مع تفعيل جدار الحماية الافتراضي UFW على الخادم، ويجب تثبيت <a href="https://academy.hsoub.com/devops/servers/databases/mongodb/" rel="">MongoDB</a> على الخادم، وتأمين قاعدة البيانات بإنشاء مستخدم إداري administrative user على قاعدة البيانات لديه صلاحية مسؤول وتفعيل المصادقة authentication في قاعدة البيانات لأنها تكون مُعطلة تلقائيًا. يمكن الاستعانة بمقال <a href="https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%AA%D8%A3%D9%85%D9%8A%D9%86-mongodb-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r435/" rel="">كيفية تثبيت وتأمين MongoDB على أوبونتو</a> فهو يتضمن كل الخطوات اللازمة.
</p>

<h2 id="1mongodb">
	الاتصال بخادم MongoDB
</h2>

<p>
	قبل البدء بتنفيذ عمليات CRUD على البيانات، علينا الاتصال بقاعدة بيانات MongoDB عبر الصدفة MongoDB Shell. فإذا كان خادم MongoDB الذي نعمل عليه مبني على خادم بعيد وليس على جهازنا المحلي، نفتح جلسة <a href="https://academy.hsoub.com/devops/security/ssh/" rel=""><abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة"><abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr></abbr></a> للاتصال به كما يلي:
</p>

<pre class="ipsCode">$ ssh sammy@your_server_ip
</pre>

<p>
	ولمطالعة المزيد من المعلومات حول <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة"><abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr></abbr> ننصح بمشاهدة الفيديو التالي:<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="603" id="ips_uid_2456_6" referrerpolicy="strict-origin-when-cross-origin" src="https://academy.hsoub.com/applications/core/interface/index.html" title="ما هي تقنية SSH" width="930" data-embed-src="https://www.youtube.com/embed/CGDYjTTDOYg"></iframe>
</p>

<p>
	بعدها نتصل بتطبيق MongoDB المُثَبَّت على الخادم بواسطة مستخدم يتمتع بصلاحيات القراءة والكتابة على البيانات،  وسيكون أمر الاتصال بالصيغة التالية:
</p>

<pre class="ipsCode">$ mongo -u AdminSammy -p --authenticationDatabase admin
</pre>

<p>
	ستُطلب منا كلمة المرور لمستخدم قاعدة البيانات وبعد كتابتها ستفتح الصدفة Shell مباشرة، ويمكن التأكد من ذلك بتغيّر شكل الموجّه في النافذة الطرفية ليصبح على هذا الشكل <code>&lt;</code> عندها تكون الصدفة جاهزة لاستقبال الأوامر التي نريد توجيهها إلى الخادم
</p>

<p>
	<strong>ملاحظة</strong>: بمجرد إنشاء اتصال جديد مع خادم MongoDB سيصلنا تلقائيًا بقاعدة البيانات الاختبارية لنظام MongoDB تدعى <code>test</code>، ويمكن الانتقال إلى قاعدة بياناتنا الخاصة باستخدام الأمر <code>use</code> متبوعًا باسم قاعدة البيانات كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2456_9" style=""><span class="pln">use database_name</span></pre>

<p>
	والآن بعد أن جهزنا الاتصال بخادم MongoDB، يمكننا البدء بالعملية الأولى من عمليات CRUD وهي Create لإنشاء مستندات جديدة.
</p>

<h2 id="2">
	إنشاء المستندات
</h2>

<p>
	سننشئ مستندات MongoDB ونستخدامها لاحقًا في تطبيق الأمثلة على عمليات القراءة والتحديث والحذف. لنفترض أننا نريد إنشاء مستندات تخزن معلومات عامة عن بعض المعالم الأثرية مثل: اسم المعلم الأثري، والبلد الذي يوجد فيه، والمدينة، وإحداثيات الموقع الجغرافي.
</p>

<p>
	ستكون المستندات التي تتضمن معلومات عن أهرامات الجيزة <code>The Pyramids of Giza</code> مثلًا وفق الصيغة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_2516_7" style=""><span class="pun">{</span><span class="pln">
    </span><span class="str">"name"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"The Pyramids of Giza"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"city"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Giza"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"country"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Egypt"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"gps"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"lat"</span><span class="pun">:</span><span class="pln"> </span><span class="lit">29.976480</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"lng"</span><span class="pun">:</span><span class="pln"> </span><span class="lit">31.131302</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُكتب مستندات MongoDB وتعالج بصيغة BSON، وهي تمثيل ثنائي لملفات <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D9%84%D9%85-json-r604/" rel="">JSON</a> سهل القراءة والفهم ويوفر بعض الإضافات التي تسمح بتخزين أنواع بيانات إضافية لا تدعمها صيغة JSON. تُمثَّل البيانات الموجودة في هذه المستندات بهيئة أزواج حقل وقيمة <code>field: value</code>.
</p>

<p>
	يتضمن المستند الذي أنشأناه أربعة حقول يشير الحقل الأول إلى اسم المعلم الأثري، يليه المدينة في الحقل الثاني، والبلد في الحقل الثالث، وتحتوي هذه الحقول الثلاثة على سلاسل نصية strings، أما الحقل الأخير والمسمى <code>gps</code>، فهو مستند متداخل nested document أي مستند داخل مستند يعرض معلومات عن الموقع الجغرافي للمكان الأثري ويتضمن إحداثيات خطوط الطول والعرض يمثلها الحقلان <code>lat</code> و <code>lng</code> والقيم ضمنهما من نوع  عدد عشري.
</p>

<p>
	تنتمي المستندات في MongoDB دائمًا إلى مجموعات collections، وهي تكافئ الجداول tables في قواعد البيانات العلاقية مثل <a href="https://academy.hsoub.com/devops/servers/databases/mysql/" rel="">MySQL</a> أما المستندات في MongoDB فهي تشبه الصفوف rows ضمن كل جدول 
</p>

<p>
	<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="639" id="ips_uid_2456_7" referrerpolicy="strict-origin-when-cross-origin" src="https://academy.hsoub.com/applications/core/interface/index.html" title="مقارنة قواعد البيانات MySQL و MongoDB" width="930" data-embed-src="https://www.youtube.com/embed/UL-gPrgoRFo"></iframe>
</p>

<p>
	وبناءً على ذلك سننشئ المستند الذي كتبنا صيغته في المثال السابق ضمن مجموعة باسم <code>monuments</code> باستخدام الأمر <code>insertOne</code> الذي ينشئ مستندًا واحدًا فقط، وهناك أمر آخر يسمح لنا بإنشاء عدة مستندات بنفس الوقت.
</p>

<p>
	لنكتب إذًا أمر الإنشاء التالي في نافذة الصدفة:
</p>

<pre class="ipsCode">&gt; db.monuments.insertOne(
&gt; {
&gt;  "name": "The Pyramids of Giza",
&gt;  "city": "Giza",
&gt;  "country": "Egypt",
&gt;  "gps": {
&gt;  "lat": 29.976480,
&gt;  "lng": 31.131302
&gt;   }
&gt;  }
&gt; )
</pre>

<p>
	نلاحظ هنا أننا لم ننشئ المجموعة <code>monuments</code> مُسبقًا قبل إدراج المستندات ضمنها، فنظام MongoDB مرن من هذه الناحية فالمجموعة ستنشأ تلقائيًا مع إدراج أول مستند فيها، وبذلك فإن التابع <code>insertOne()‎</code> لم يُنشئ المستند فحسب بل أنشأ المجموعة أيضًا.
</p>

<p>
	سنحصل على الخرج التالي الذي يعلمنا بنجاح تنفيذ التابع <code>insertOne()‎</code> وإنشاء المستند المطلوب، بالإضافة إلى إرجاع مُعَرّف الكائن <code>ObjectId</code> الخاص به والذي ينشأ تلقائيًا لكل كائن أو مستند جديد:
</p>

<pre class="ipsCode">{
  "acknowledged" : true,
  "insertedId" : ObjectId("6105752352e6d1ebb7072647")
}
</pre>

<p>
	ينبغي أن يتضمن كل مستند في مجموعة MongoDB حقلًا خاصًا بالمُعَرِّف الفريد <code>id_</code> للمستند والذي كمفتاح رئيسي primary key، يمكنك إعطاء الحقل <code>id_</code> أي قيمة نختارها طالما أننا ملتزمون تمامًا بالحفاظ على قيمة فريدة له وعدم تكراره بين المستندات، وبكل الأحوال إذا أهملنا هذا الحقل عند إنشاء أي مستند جديد فإن MongoDB ستُنشئه نيابةً عنا ويكون بهيئة كائن <code>ObjectId</code> كما شاهدنا في الخرج السابق.
</p>

<p>
	للتأكد من صحة الإنشاء، يمكن تفقد عدد المستندات في المجموعة <code>monuments</code> باستخدام الأمر التالي:
</p>

<pre class="ipsCode">&gt; db.monuments.count()
</pre>

<p>
	سيُرجع التابع <code>count</code> القيمة <code>1</code> لأننا أدخلنا مستندًا واحدًا فقط في المجموعة:
</p>

<pre class="ipsCode">1
</pre>

<p>
	توفر MongoDB طريقةً سهلة لإدخال عدة مستندات إلى المجموعة بعملية واحدة عبر التابع <code>insertMany</code> فالإدخال الفردي قد يصبح مرهقًا إذا كانت المستندات معقدة وكثيرة العدد. على سبيل المثال ينشئ الأمر التالي ستة مستندات دفعة واحدة ضمن المجموعة <code>monuments</code>:
</p>

<pre class="ipsCode">&gt; db.monuments.insertMany([
&gt;    {"name": "The Valley of the Kings", "city": "Luxor", "country": "Egypt", "gps": { "lat": 25.746424, "lng": 32.605309 }},
&gt;    {"name": "Arc de Triomphe", "city": "Paris", "country": "France", "gps": { "lat": 48.873756, "lng": 2.294946 }},
&gt;    {"name": "The Eiffel Tower", "city": "Paris", "country": "France", "gps": { "lat": 48.858093, "lng": 2.294694 }},
&gt;    {"name": "Acropolis", "city": "Athens", "country": "Greece", "gps": { "lat": 37.970833, "lng": 23.726110 }},
&gt;    {"name": "The Great Wall of China", "city": "Huairou", "country": "China", "gps": { "lat": 40.431908, "lng": 116.570374 }},
&gt;    {"name": "The Statue of Liberty", "city": "New York", "country": "USA", "gps": { "lat": 40.689247, "lng": -74.044502 }}
&gt; ])
</pre>

<p>
	تُحيط الأقواس المربعة <code>[</code><code>]</code> بالمستندات الستة في المثال أعلاه، فهي تشكل مصفوفة من العناصر، ويفصل بين كل عنصر وآخر فاصلة <code>, </code>فعندما نريد تمرير عدة كائنات في MongoDB أيًّا كان نوعها نمررها بشكل مصفوفة بين قوسين مربعين.
</p>

<p>
	بمجرد تنفيذ أمر الإنشاء السابق سيظهر الخرج التالي ليعلمنا بنجاح العملية ويرجع المعرّفات الفريدة لكل مستند:
</p>

<pre class="ipsCode">{
  "acknowledged" : true,
  "insertedIds" : [
    ObjectId("6105770952e6d1ebb7072648"),
    ObjectId("6105770952e6d1ebb7072649"),
    ObjectId("6105770952e6d1ebb707264a"),
    ObjectId("6105770952e6d1ebb707264b"),
    ObjectId("6105770952e6d1ebb707264c"),
    ObjectId("6105770952e6d1ebb707264d")
  ]
}
</pre>

<p>
	لنتأكد من صحة أمر إنشاء المستندات الجديدة بالاستعلام عن عدد المستندات في المجموعة <code>monuments</code>:
</p>

<pre class="ipsCode">&gt; db.monuments.count()
</pre>

<p>
	سنحصل على الخرج التالي الذي يوضح أن عدد المستندات في المجموعة أصبح <code>7</code> بعد إضافة ستة مستندات جديدة إلى المستند الأول:
</p>

<pre class="ipsCode">7
</pre>

<p>
	بعد أن أنشانا المستندات، لننتقل للخطوة التالية التي تشرح كيفية قراءة هذه البيانات من هذه المستندات.
</p>

<h2 id="3">
	قراءة المستندات
</h2>

<p>
	أصبح لدينا مجموعة تتضمن سبعة مستندات، ويمكننا الاستعلام عنها من قاعدة البيانات، سنعرض في البداية طريقة الاستعلام عن جميع مستندات المجموعة من دون استثناء، ثم سنتعلم تضييق نطاق الاستعلام لنحصل على مجموعة أقل من المستندات.
</p>

<p>
	لنبدأ بقراءة المستندات السبعة من المجموعة <code>monuments</code> بعملية واحد باستخدام التابع <code>()find</code>:
</p>

<pre class="ipsCode">&gt; db.monuments.find()
</pre>

<p>
	يؤدي استخدام التابع <code>()find</code> بدون وسطاء إلى إرجاع جميع البيانات الموجودة في المجموعة المحددة وهي في حالتنا المجموعة <code>monuments</code> وسنحصل بالتالي على هذا الخرج:
</p>

<pre class="ipsCode">{ "_id" : ObjectId("6105752352e6d1ebb7072647"), "name" : "The Pyramids of Giza", "city" : "Giza", "country" : "Egypt", "gps" : { "lat" : 29.97648, "lng" : 31.131302 } }
{ "_id" : ObjectId("6105770952e6d1ebb7072648"), "name" : "The Valley of the Kings", "city" : "Luxor", "country" : "Egypt", "gps" : { "lat" : 25.746424, "lng" : 32.605309 } }
{ "_id" : ObjectId("6105770952e6d1ebb7072649"), "name" : "Arc de Triomphe", "city" : "Paris", "country" : "France", "gps" : { "lat" : 48.873756, "lng" : 2.294946 } }
{ "_id" : ObjectId("6105770952e6d1ebb707264a"), "name" : "The Eiffel Tower", "city" : "Paris", "country" : "France", "gps" : { "lat" : 48.858093, "lng" : 2.294694 } }
{ "_id" : ObjectId("6105770952e6d1ebb707264b"), "name" : "Acropolis", "city" : "Athens", "country" : "Greece", "gps" : { "lat" : 37.970833, "lng" : 23.72611 } }
{ "_id" : ObjectId("6105770952e6d1ebb707264c"), "name" : "The Great Wall of China", "city" : "Huairou", "country" : "China", "gps" : { "lat" : 40.431908, "lng" : 116.570374 } }
{ "_id" : ObjectId("6105770952e6d1ebb707264d"), "name" : "The Statue of Liberty", "city" : "New York", "country" : "USA", "gps" : { "lat" : 40.689247, "lng" : -74.044502 } }
</pre>

<p>
	تعرض الصدفة MongoDB Shell المستندات السبعة بكامل حقولها، ونلاحظ أن لكل حقل مُعَرّف خاص <code>id_</code> رغم أننا لم نُعَرِّفه عند إنشاء المستندات، وذلك لأن MongoDB كما ذكرنا تُنشئ المُعرفات تلقائيًا مع أوامر الإدخال وهي تعمل كمفاتيح رئيسية للمستندات الخاصة بها.
</p>

<p>
	نلاحظ أيضًا أن طريقة عرض البيانات ضمن الصدفة MongoDB Shell صعب القراءة نوعًا ما، وخاصة إذا كانت المستندات كثيرة الحقول أو تتضمن مستندات متداخلة فالمستند الواحد سيظهر بجميع بياناته بسطر واحد، ويمكن تحسين الإظهار وجعله أسهل في القراءة باستخدام الخاصية <code>()pretty</code> مع التابع <code>()find</code> كما يلي:
</p>

<pre class="ipsCode">&gt; db.monuments.find().pretty()
</pre>

<p>
	الآن ستعرض الصدفة MongoDB Shell الخرج بالطريقة التالية، حيث تفرد لكل مستند عدة أسطر يبدأ كل منها بمسافة بادئة indentation:
</p>

<pre class="ipsCode">{
  "_id" : ObjectId("6105752352e6d1ebb7072647"),
  "name" : "The Pyramids of Giza",
  "city" : "Giza",
  "country" : "Egypt",
  "gps" : {
    "lat" : 29.97648,
    "lng" : 31.131302
  }
}
{
  "_id" : ObjectId("6105770952e6d1ebb7072648"),
  "name" : "The Valley of the Kings",
  "city" : "Luxor",
  "country" : "Egypt",
  "gps" : {
    "lat" : 25.746424,
    "lng" : 32.605309
  }
}
. . .
</pre>

<p>
	لنستخدم بعض الوسطاء مع التابع <code>()find</code> لتضييق نتائج البحث فمثالنا السابق أرجع كافة مستندات المجموعة من دون أي تصفية.
</p>

<p>
	ذكرنا سابقًا أن MongoDB تعطي مُعَرِّفًا فريدًا لكل مستند، لنأخذ مثلًا المستند المُسمى "The Valley of the Kings" والذي يشير لأحد المعالم الأثرية في مجموعتنا وله المُعرِّف <code>‎ObjectId("6105770952e6d1ebb7072648")‎</code> الذي يميزه عن غيره، علمًا أن مُعرِّف الكائن <code>ObjectId</code> ليس من مجرد سلسلة ست عشرية فهو بحد ذاته كائن أيضًا وهو نوع خاص من البيانات تستخدمه MonogoDB لتخزين مُعَرِّفات الكائنات،  ويمكن مطالعة المزيد عن <a href=")" rel="">أنواع البيانات التي تتعامل معها MongoDB</a>.
</p>

<p>
	سُنمَرِّر الآن هذا المُعَرِّف كوسيط للتابع <code>()find</code> بهيئة مستند يسمى مستند تصفية الاستعلام query filter document، تتمتع مستندات تصفية الاستعلام بنفس بنية مستندات مجموعة البيانات أي بنية حقل وقيمة لكنها تستخدم لغرض خاص هو تصفية نتائج الاستعلام.
</p>

<p>
	يتضمن مستند تصفية الاستعلام في حالتنا الحقل <code>id_</code> والقيمة التي تمثل <code>Objectid</code> للمستند "The Valley of the Kings"، وسيأخذ الاستعلام عندها الصيغة التالية:
</p>

<pre class="ipsCode">&gt; db.monuments.find({"_id": ObjectId("6105770952e6d1ebb7072648")}).pretty()
</pre>

<p>
	يستخدم مستند تصفية الاستعلام في هذا المثال شرط المساواة لإرجاع النتائج، فستُرجع <code>()find</code> المستند الذي يطابق معرفه <code>id_</code> القيمة <code>‎ObjectId("6105770952e6d1ebb7072648")‎</code> فقط ولن تُرجع معه أي مستند آخر.
</p>

<p>
	سنحصل في هذه الحالة على الخرج التالي:
</p>

<pre class="ipsCode">{
  "_id" : ObjectId("6105770952e6d1ebb7072648"),
  "name" : "The Valley of the Kings",
  "city" : "Luxor",
  "country" : "Egypt",
  "gps" : {
    "lat" : 25.746424,
    "lng" : 32.605309
  }
}
</pre>

<p>
	لنجرب مثالًا آخر، سنستعلم هنا عن جميع المعالم الأثرية الموجودة في فرنسا أي التي تحقق الشرط التالي:
</p>

<pre class="ipsCode">&gt; db.monuments.find({"country": "France"}).pretty()
</pre>

<p>
	سيُرجع هذا الاستعلام نتيجتين كما يلي:
</p>

<pre class="ipsCode">{
  "_id" : ObjectId("6105770952e6d1ebb7072649"),
  "name" : "Arc de Triomphe",
  "city" : "Paris",
  "country" : "France",
  "gps" : {
    "lat" : 48.873756,
    "lng" : 2.294946
  }
}
{
  "_id" : ObjectId("6105770952e6d1ebb707264a"),
  "name" : "The Eiffel Tower",
  "city" : "Paris",
  "country" : "France",
  "gps" : {
    "lat" : 48.858093,
    "lng" : 2.294694
  }
}
</pre>

<h2 id="4">
	الخطوة 4: تحديث المستندات
</h2>

<p>
	يُقصد بتحديث المستندات Updating Documents في <a href="https://academy.hsoub.com/devops/servers/databases/mongodb/" rel="">قواعد بيانات MongoDB</a> إما تغيير بنية المستند نفسه بإضافة أو تعديل الحقول لتناسب متطلبات جديدة في التطبيق مثلًا، أو تعديل قيم البيانات المُخَزَّنة ضمن المستند، سنناقش أمثلةًعن كلا الحالتين إذ سنُعَدِّل بعض القيم في المستندات وسنضيف حقلًا جديدًا إلى مستندات المجموعة.
</p>

<p>
	توفر MongoDB طريقتين لتحديث المستندات إما فرديًا أو جماعيًا، في التحديث الجماعي للمستندات يتعين علينا تمرير القيم التي نريد تحديثها كوسيط لتابع التحديث، وفي التحديث الفردي نمرر مُعَرِّف المستند الذي نود تعديله إضافةً إلى القيم الجديدة.
</p>

<p>
	تستخدم MongoDB آلية مستند تصفية الاستعلام query filter document نفسها التي استخدمناها في الفقرة السابقة، وذلك للسماح للمستخدم بتحديد المستندات التي يود تحديثها.
</p>

<p>
	يبين المثال التالي طريقة تغيير اسم أحد المعالم الأثرية وليكن مثلًا قوس النصر <code>Arc de Triomphe</code> حيث سنغير اسمه إلى <code>Arc de Triomphe de l’Étoile</code>، باستخدام التابع <code>()updateOne</code> المخصص لتحديث مستند واحد فقط في كل عملية:
</p>

<pre class="ipsCode">&gt; db.monuments.updateOne(
&gt;   { "name": "Arc de Triomphe" },
&gt;   {
&gt;     $set: { "name": "Arc de Triomphe de l'Étoile" }
&gt;   }
&gt; )
</pre>

<p>
	سيكون اسم المستند الذي نرغب بتعديله هو الوسيط الأول للتابع <code>()updateOne</code> وهو في حالتنا <code>{ "name": "Arc de Triomphe" }</code> وهو مستند تصفية استعلام مع شرط المساواة، وبالتالي سيُرجع لنا المستند الذي يطابق اسمه تمامًا القيمة المذكورة، وسيكون هو المستند الذي ننفذ عليه التعديل.
</p>

<p>
	أما الوسيط الثاني فهو مستند التحديث update document الذي يتضمن التحديثات التي ينبغي أن تُطَبَّق عند تنفيذ التابع، يتكون مستند التحديث من عوامل تحديث operators تلعب دور المفاتيح keys، ومعاملات parameters مقابلة تمثل القيم الجديدة values. في حالتنا عامل التحديث هو <code>set$</code> وهو المسؤول عن إعطاء قيم جديدة لحقول المستند التي تُكتب بصيغة كائنات JSON مثل <code>{ "name": "Arc de Triomphe de l'Étoile" }</code> الذي يعني ضمنًا تعديل قيمة الحقل <code>name</code> لتصبح <code>Arc de Triomphe de l'Étoile</code>.
</p>

<p>
	يُرجع تابع التحديث <code>()updateOne</code> خرجًا يخبرنا بنتيجة عمله، فقد عثر على مستند واحد مطابق للشروط، وحَدَّث قيمته بنجاح، كما يلي:
</p>

<pre class="ipsCode">{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
</pre>

<p>
	<strong>تنويه</strong>: قد لا يكون مستند تصفية الاستعلام المستخدم كوسيط أول للتابع <code>()updateOne</code> مُحَددًا ودقيقًا بما يكفي لإعطائنا نتيجة واحدة فيُرجِع عدة مستندات تتوافق مع شروط الاستعلام بدلًا من واحد، في هذه الحالة سيأخذ التابع <code>()updateOne</code> أول مستند من هذه المستندات ويطَبِّق التعديلات عليه ويهمل البقية لأنه في نهاية الأمر مُخصص للعمل مع مستند واحد.
</p>

<p>
	لنتأكد الآن من نجاح عملية التحديث، سنطلب جميع المعالم الأثرية الموجودة في فرنسا <code>France</code> وفق الآتي:
</p>

<pre class="ipsCode">&gt; db.monuments.find({"country": "France"}).pretty()
</pre>

<p>
	يؤكد لنا الخرج التالي تغيير طريقة كتابة <code>Arc de Triomphe</code> وبالتالي نجاح عملية التحديث:
</p>

<pre class="ipsCode">{
  "_id" : ObjectId("6105770952e6d1ebb7072649"),
  "name" : "Arc de Triomphe de l'Étoile",
  "city" : "Paris",
  "country" : "France",
  "gps" : {
    "lat" : 48.873756,
    "lng" : 2.294946
  }
}
. . .
</pre>

<p>
	سنستعمل الآن التابع <code>()updateMany</code> لتعديل أكثر من مستند في نفس الوقت.
</p>

<p>
	لنفترض مثلًا أننا نريد إضافة حقل إلى كل مستند من مستندات المجموعة، يبين هذا الحقل اسم المُحرِّر <code>editor</code> الذي أدخل بيانات المعلم الأثري. طالما أننا سنُنَفِّذ التعديل على جميع المستندات في المجموعة، فسنستخدم إذًا مستند تصفية استعلام فارغ بلا أي شروط وبسببه سيؤثر <code>()updateMany</code> على جميع مستندات المجموعة <code>monuments</code> ويُضيف إلى كل واحد منها حقلًا جديدًا يدعى <code>editor</code> ويحمل القيمة <code>Sammy</code> وفق التالي:
</p>

<pre class="ipsCode">&gt; db.monuments.updateMany(
&gt;   { },
&gt;   {
&gt;    $set: { "editor": "Sammy" }
&gt;   }
&gt; )
</pre>

<p>
	سيعطي هذا التابع الخرج التالي الذي يعلمنا بنتيجة التنفيذ:
</p>

<pre class="ipsCode">{ "acknowledged" : true, "matchedCount" : 7, "modifiedCount" : 7 }
</pre>

<p>
	عثرنا على سبعة مستندات مطابقة للشروط، وعَدَّلنا المستندات السبعة بنجاح.
</p>

<p>
	يمكن التأكد من إضافة الحقل الجديد إلى مستندات المجموعة بواسطة الأمر التالي:
</p>

<pre class="ipsCode">&gt; db.monuments.find().pretty()
</pre>

<p>
	وسيكون الخرج كما يلي:
</p>

<pre class="ipsCode">{
  "_id" : ObjectId("6105752352e6d1ebb7072647"),
  "name" : "The Pyramids of Giza",
  "city" : "Giza",
  "country" : "Egypt",
  "gps" : {
    "lat" : 29.97648,
    "lng" : 31.131302
  },
  "editor" : "Sammy"
}
{
  "_id" : ObjectId("6105770952e6d1ebb7072648"),
  "name" : "The Valley of the Kings",
  "city" : "Luxor",
  "country" : "Egypt",
  "gps" : {
    "lat" : 25.746424,
    "lng" : 32.605309
  },
  "editor" : "Sammy"

}
. . .
</pre>

<p>
	كما نلاحظ فقد أُضيف حقل جديد إلى كل مستندات المجموعة، فإعطاء اسم حقل غير موجود للعامل <code>set$</code> في تابع التحديث يعني أننا نطلب منه إنشاء هذا الحقل ومنحه القيمة المحددة.
</p>

<p>
	يُعدّ <code>set$</code> عاملًا شائع الاستخدام وسيفيدنا في كثير من الحالات، مع ذلك توفر MongoDB قائمة طويلة من عوامل التعديل التي تساعدنا على إجراء تحديثات متنوعة ومعقدة على المستندات ويمكن معرفة المزيد عنها من <a href="https://www.mongodb.com/docs/manual/reference/operator/update/" rel="external nofollow">توثيقات MongoDB الرسمية</a>.
</p>

<h2 id="5">
	حذف المستندات
</h2>

<p>
	إذا احتجنا لحذف بعض البيانات القديمة من قاعدة بيانات MongoDB فيمكن استخدام تابعين للحذف الأول هو التابع <code>()deleteOne</code> لحذف مستند واحد من المستندات المطابقة لشروط مستند تصفية الاستعلام، والثاني هو التابع <code>()deleteMany</code> لحذف عدة مستندات دفعة واحدة.
</p>

<p>
	لنحاول حذف المستند الخاص بقوس النصر <code>Arc de Triomphe de l’Étoile</code> الذي عَدَّلنا اسمه قبل قليل، وذلك وفق الأمر التالي:
</p>

<pre class="ipsCode">&gt; db.monuments.deleteOne(
&gt;     { "name": "Arc de Triomphe de l'Étoile" }
&gt; )
</pre>

<p>
	نلاحظ أن مستند تصفية الاستعلام المستخدم هنا مشابه لما استخدمناه في الأمثلة السابقة عند القراءة والتحديث، ويمكن بالتأكيد استخدام أي استعلام مكتوب بطريقة صحية لتحديد المستند الذي نريد حذفه.
</p>

<p>
	نحصل بعد التنفيذ على خرج يشبه التالي:
</p>

<pre class="ipsCode">{ "acknowledged" : true, "deletedCount" : 1 }
</pre>

<p>
	يبين هذا الخرج عدد المستندات المحذوفة بموجب الأمر السابق.
</p>

<p>
	والآن لنتأكد من حذف المستند بالاستعلام عن الآثار الموجودة في فرنسا وفق التالي:
</p>

<pre class="ipsCode">&gt; db.monuments.find({"country": "France"}).pretty() 
</pre>

<p>
	ستتضمن نتيجة الاستعلام المستند الخاص ببرج إيفل <code>The Eiffel Tower</code> فقط لأننا حذفنا مستند قوس النصر <code>Arc de Triomphe de l’Étoile</code>:
</p>

<pre class="ipsCode">{
  "_id" : ObjectId("6105770952e6d1ebb707264a"),
  "name" : "The Eiffel Tower",
  "city" : "Paris",
  "country" : "France",
  "gps" : {
    "lat" : 48.858093,
    "lng" : 2.294694
  },
  "editor" : "Sammy"
}
</pre>

<p>
	لنشرح الآن طريقة حذف مستندات متعددة، ولنحذف مثلًا كافة المستندات التي أنشأها المحرر الذي اسمه <code>Sammy</code>، طبعًا سيؤدي هذا إلى حذف جميع مستندات المجموعة لأن <code>Sammy</code> هو المحرر الذي أضفناه لكافة مستندات المجموعة <code>monuments</code>:
</p>

<pre class="ipsCode">&gt; db.monuments.deleteMany(
&gt;  { "editor": "Sammy" }
&gt; )
</pre>

<p>
	سيعلمنا الخرج بحذف ستة مستندات:
</p>

<pre class="ipsCode">{ "acknowledged" : true, "deletedCount" : 6 }
</pre>

<p>
	ويمكن التأكد من النتيجة بالاستعلام عن عدد مستندات المجموعة <code>monuments</code> كما يلي:
</p>

<pre class="ipsCode">&gt; db.monuments.count()
</pre>

<p>
	سنحصل على الخرج التالي:
</p>

<pre class="ipsCode">0
</pre>

<p>
	تعني النتيجة <code>0</code> حذف جميع المستندات في المجموعة.
</p>

<h2 id="-1">
	الخاتمة
</h2>

<p>
	تعرفنا في هذا المقال على طريقة تطبيق عمليات CRUD على قاعدة بيانات MongoDB، إذ تُعَدّ هذه العمليات أساسية في إدارة البيانات ويمكن من خلالها إنشاء مستندات جديدة وتعديلها والاستعلام عنها وحذفها عند الضرورة.
</p>

<p>
	وننوه في الختام أننا عرضنا في هذا المقال طريقةً واحدة فقط من طرق تصفية الاستعلام، لكن MongoDB توفر طرقًا أخرى أقوى وأكثر تعقيدًا ويمكنكم تعلم المزيد عنها بمراجعة <a href="https://academy.hsoub.com/devops/servers/databases/mongodb/" rel="">قسم MongoDB</a> على أكاديمية حسوب و<a href="https://docs.mongodb.com/v4.4/mongo/" rel="external nofollow">توثيقات MongoDB الرسمية</a>.
</p>

<p>
	ترجمة -وبتصرف- لمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-perform-crud-operations-in-mongodb" rel="external nofollow">How To Perform CRUD Operations in MongoDB</a> لصاحبه Mateusz Papiernik.
</p>
]]></description><guid isPermaLink="false">842</guid><pubDate>Sun, 13 Apr 2025 15:00:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x62B;&#x628;&#x64A;&#x62A; &#x648;&#x62A;&#x623;&#x645;&#x64A;&#x646; MongoDB &#x639;&#x644;&#x649; &#x623;&#x648;&#x628;&#x648;&#x646;&#x62A;&#x648; 18.04</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%AA%D8%A3%D9%85%D9%8A%D9%86-mongodb-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r435/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_08/5d46bb8379025_MongoDB.jpg.eef9aa2852e64c083af553300fbc725f.jpg" /></p>

<p>
	<a href="https://academy.hsoub.com/devops/servers/databases/mongodb/" rel="">MongoDB</a> عبارة عن قاعدة بيانات NoSQL مستندات مجانية ومفتوحة المصدر تُستخدم غالبا في تطبيقات الويب الحديثة.
</p>

<p>
	في هذا المقال سنُثبِّت MongnDB، ونُدير خدماتها، ونحميها، ونُفعل الوصول البعيد لها.
</p>

<h2 id="-">
	المتطلبات
</h2>

<p>
	تحتاج لتطبيق هذا الدرس إلى خادم أوبونتو مُعَد باتباع <a href="%D8%B1%D8%A7%D8%A8%D8%B7%20%D9%85%D9%82%D8%A7%D9%84%201" rel="">مقال الإعداد الأولي</a>، ويحتوي على مستخدم sudo غير مسؤول وجدار حماية.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_08/5d46bb8012686_MongoDB.jpg.8bb617a227a867393757f2a0314b4b9a.jpg" data-fileid="30949" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="30949" data-unique="1iujjqy0u" src="https://academy.hsoub.com/uploads/monthly_2019_08/5d46bb8027488_MongoDB.thumb.jpg.14d3326c85e5eb847b0e13513123c506.jpg" alt="كيفية تثبيت MongoDB.jpg"></a>
</p>

<h2 id="-mongodb">
	الجزء الأول: تثبيت MongoDB
</h2>

<h3 id="-1-mongodb">
	خطوة 1 - تثبيت MongoDB
</h3>

<p>
	حزمة مخزن أوبونتو الرسمي يحتوي على نسخة مُحدثه من MongoDB، ما يعني أنه بإمكاننا تثبيت حزماتِه المهمة باستخدام <code>apt</code>.
</p>

<p>
	بداية حدِّث قائمة الحُزم كي تحصل على أحدث الاصدارات:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo apt update
</pre>

<p>
	الآن ثبّت حزمة MongoDB:
</p>

<pre class="ipsCode">
 $ sudo apt <span class="hljs-keyword">install</span> -y mongodb
</pre>

<p>
	يُثبّت هذا الأمر عدة حُزم تحتوي على أحدث إصدار من MongoDB بالاضافة إلى أدوات إدارة مساعدة لخادم MongoDB. يبدأ خادم قاعدة البيانات بالعمل تلقائيا بعد التثبيت.
</p>

<p>
	تاليًا، نتحقق ما إن كان الخادم بعمل بصورة صحيحة.
</p>

<h3 id="-2-">
	خطوة 2 - التحقق من الخدمة وقاعدة البيانات
</h3>

<p>
	قامت عملية تثبيت MongoDB بتشغيله تلقائيا، لكن لنتأكد من بدء الخدمة ومن صحة عمل قاعدة البيانات.
</p>

<p>
	أولا تحقق من حالة الخدمة:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo systemctl status mongodb
</pre>

<p>
	سترى هذه المخرجات:
</p>

<pre class="ipsCode">
● mongodb.service - An object/document-oriented database
<span class="hljs-symbol">   Loaded:</span> loaded (<span class="hljs-meta-keyword">/lib/</span>systemd<span class="hljs-meta-keyword">/system/</span>mongodb.service; enabled; vendor preset: enabled)
<span class="hljs-symbol">   Active:</span> active (running) since Sat <span class="hljs-number">2018</span><span class="hljs-number">-05</span><span class="hljs-number">-26</span> <span class="hljs-number">07</span>:<span class="hljs-number">48</span>:<span class="hljs-number">04</span> UTC; <span class="hljs-number">2</span>min <span class="hljs-number">17</span>s ago
<span class="hljs-symbol">     Docs:</span> man:mongod(<span class="hljs-number">1</span>)
 Main <abbr title="Process IDentifier | معرّف العملية أو البرنامج">PID</abbr>: <span class="hljs-number">2312</span> (mongod)
<span class="hljs-symbol">    Tasks:</span> <span class="hljs-number">23</span> (limit: <span class="hljs-number">1153</span>)
<span class="hljs-symbol">   CGroup:</span> /system.slice/mongodb.service
           └─<span class="hljs-number">2312</span> <span class="hljs-meta-keyword">/usr/</span>bin/mongod --unixSocketPrefix=<span class="hljs-meta-keyword">/run/</span>mongodb --config <span class="hljs-meta-keyword">/etc/</span>mongodb.conf
</pre>

<p>
	يصرِّح <code>systemd</code> أنَّ خادم MongoDB يعمل.
</p>

<p>
	يمكننا التحقق أكثر عن طريق الاتصال بخادم قاعدة البيانات وتنفيذ أمر للفحص .نفّذ الأمر التالي:
</p>

<pre class="ipsCode">
 $ mongo --<span class="hljs-built_in">eval</span> <span class="hljs-string">'db.runCommand({ connectionStatus: 1 })'</span>
</pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
MongoDB <span class="hljs-keyword">shell</span> <span class="hljs-keyword">version</span> v3.<span class="hljs-number">6.3</span>
connecting <span class="hljs-keyword">to</span>: mongod<span class="hljs-variable">b:</span>//<span class="hljs-number">127.0</span>.<span class="hljs-number">0.1</span>:<span class="hljs-number">27017</span>
MongoDB server <span class="hljs-keyword">version</span>: <span class="hljs-number">3.6</span>.<span class="hljs-number">3</span>
{
        <span class="hljs-string">"authInfo"</span> : {
                <span class="hljs-string">"authenticatedUsers"</span> : [ ],
                <span class="hljs-string">"authenticatedUserRoles"</span> : [ ]
        },
        <span class="hljs-string">"ok"</span> : <span class="hljs-number">1</span>
}
</pre>

<p>
	القيمة <code>1</code> للحقل <code>ok</code> تعني أن الخادم يعمل بطريقة صحيحة.
</p>

<p>
	بعد ذلك، سنتطرق إلى كيفية إدارة حالة الخادم.
</p>

<h3 id="-3-mongodb">
	خطوة 3 - إدارة خدمة MongoDB
</h3>

<p>
	تُثبت MongoDB كخدمة ضمن النظام، ما يعني أنه يُمكنك إدارتها باستخدام أوامر <code>systemd</code> القياسية مثل باقي خدمات النظام على أوبونتو.
</p>

<p>
	لتتأكد من حالة الخدمة نفذ الأمر:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo systemctl status mongodb
</pre>

<p>
	يمكنك إيقاف الخادم في أي وقت من خلال الأمر:
</p>

<pre class="ipsCode">
 $ sudo systemctl <span class="hljs-built_in">stop</span> mongodb
</pre>

<p>
	لبدء الخادم عندما يكون متوقفًا عن العمل:
</p>

<pre class="ipsCode">
 $ sudo systemctl <span class="hljs-literal">start</span> mongodb
</pre>

<p>
	يمكن إعادة تشغيل الخادم باستخدام أمر واحد:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo systemctl restart mongodb
</pre>

<p>
	MongoDB مُعد لِلبدء تلقائيا مع بدء الخادم، لإيقاف البدء التلقائي:
</p>

<pre class="ipsCode">
 $ sudo systemctl <span class="hljs-built_in">disable</span> mongodb
</pre>

<p>
	لتفعيل الميزة مجددا:
</p>

<pre class="ipsCode">
 $ sudo systemctl <span class="hljs-built_in">enable</span> mongodb
</pre>

<p>
	تاليًا، إعداد جدار الحماية لعملية تثبيت MongoDB.
</p>

<h3 id="-4-">
	خطوة 4 - إعداد جار الحماية (اختياري)
</h3>

<p>
	بافتراض أنك اتبعت مقال الإعداد الأولي لخادم أوبونتو لِتفعيل جدار الحماية، فإن خادم MongoDB لا يمكن أن يُوصل من خلال الإنترنت.
</p>

<p>
	في حال كنت تنوي استخدام خادم MongoDB محليا مع التطبيقات على نفس الخادم فقط فهذا الإعداد هو الأمثل. لكن إن كنت تريد أن تتصل بخادم قاعدة بيانات MongoDB من خلال الانترنت فيجب أن تسمح للاتصالات الخارجية في <code><a href="https://academy.hsoub.com/devops/security/firewalls/%D9%83%D9%8A%D9%81-%D8%AA%D8%B6%D8%A8%D8%B7-%D8%AC%D8%AF%D8%A7%D8%B1%D8%A7-%D9%86%D8%A7%D8%B1%D9%8A%D8%A7-%D9%81%D9%8A-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-ufw-r120/" rel="">ufw</a></code>.
</p>

<p>
	للسماح بالوصول من أي مكان إلى MongoDB على المنفذ الافتراضي <code>27017</code> يمكنك استخدام <code>sudo ufw allow 27017</code>. لكن تفعيل وصول الإنترنت إلى خادم MongoDB في التثبيت الافتراضي يعطي دخول غير محدود بضوابط لِخادم قاعدة البيانات وبياناته.
</p>

<p>
	في معظم الحالات يجب الوصول إلى MongoDB من أماكن موثوقة معينة فقط، مثل خادم آخر يستضيف تطبيقا مًا. للقيام بذلك، يمكنك السماح بالوصول إلى منفذ MongoDB الافتراضي مع تحديد عنوان بروتوكول الإنترنت للخادم الآخر الذي سيتمكن من الوصول إلى خادم MongoDB مباشرة:
</p>

<pre class="ipsCode">
 $ sudo ufw allow <span class="hljs-keyword">from</span> your_other_server_ip/<span class="hljs-number">32</span> <span class="hljs-keyword">to</span> <span class="hljs-literal">any</span> <span class="hljs-keyword">port</span> <span class="hljs-number">27017</span>
</pre>

<p>
	يمكنك التحقق من التغييرات في جدار الحماية باستخدام <code>ufw</code>:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo ufw status
</pre>

<p>
	يجب أن ترى أن حركة المرور للمنفذ <code>27017</code> متاحة في المخرجات "output":
</p>

<pre class="ipsCode">
<span class="hljs-attribute">Status</span>: active

<span class="lisp">To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
<span class="hljs-number">27017</span>                      ALLOW       Anywhere
OpenSSH (<span class="hljs-name">v6</span>)               ALLOW       Anywhere (<span class="hljs-name">v6</span>)
<span class="hljs-number">27017</span> (<span class="hljs-name">v6</span>)                 ALLOW       Anywhere (<span class="hljs-name">v6</span>)</span>
</pre>

<p>
	إن كنت قد قمت بتحديد عنوان بروتوكول إنترنت معين للاتصال بخادم MongoDB، فستراه بدلا من كلمة <code>Anywhere</code> في المخرجات.
</p>

<p>
	للمزيد من إعدادات جدار الحماية المتقدمة لحد الوصول إلى خدمات <a href="https://academy.hsoub.com/devops/security/firewalls/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-ufw-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D9%88%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D9%84%D9%84%D8%AC%D8%AF%D8%A7%D8%B1-%D8%A7%D9%84%D9%86%D8%A7%D8%B1%D9%8A-r121/" rel="">UFW الأساسية: قواعد وأوامر جدار الحماية الشائعة</a>.
</p>

<p>
	على الرغم من أنَّ المنفذ مفتوح، إلا أن MongoDB يسمع فقط للعنوان المحلي <code>127.0.0.1</code>. للسماح بالوصول من بعد، أضف عنوان بروتوكول الخادم العام و القابل للتوجيه إلى ملف <code>mongod.conf</code>.
</p>

<p>
	افتح ملف ضبط MongoDB:
</p>

<pre class="ipsCode">
 $ sudo nano <span class="hljs-regexp">/etc/m</span>ongodb.conf
</pre>

<p>
	أضف عنوان بروتوكول الانترنت الخاص بالخادم إلى قيمة <code>bindIP</code>:
</p>

<pre class="ipsCode">
<span class="hljs-params">...</span>
logappend=<span class="hljs-literal">true</span>

bind_ip = <span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>,your_server_ip
#port = <span class="hljs-number">27017</span>

<span class="hljs-params">...</span>
</pre>

<p>
	لا تنسَ وضع فاصلة بين عناوين بروتوكول الإنترنت الموجودة والعنوان الذي أضفته الآن.
</p>

<p>
	احفظ الملف واغلقه، ثم أعد تشغيل MongoDB:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo systemctl restart mongodb
</pre>

<h2 id="-mongodb">
	الجزء الثاني: تأمين MongoDB
</h2>

<p>
	كانت الاصدارات السابقة ل MongoDB مُعرَّضة للاختراق لأنَّها لا تتطلب أي مصادقة للتفاعل مع قاعدة البيانات. يمكن لأي مستخدم إنشاء وحذف قواعد بيانات وقراءة محتواها والكتابة فيها تلقائيا. أعدَّت أيضا هذه الاصدارات برنامج MongoDB خفي يسمع لجميع الواجهات تلقائيًا، مما يعني أن السكربتات التلقائية يمكن أن تكتشف حالات MongoDB الغير محمية بجدار حماية، وإن لم تكُن المصادقة مفعلة، يمكن لهذه السكربتات الحصول على وصول كامل إلى MongoDB.
</p>

<p>
	خُفِّفَت الحالة في الاصدار ‎3.x وبعض الاصدارات السابقة المُقدَّمة من بعض مديري الحُزم لأن البرنامج الخفي أصبح الآن مرتبط ب 127.0.0.1، لذلك سيقبل الاتصالات على حزمة يونكس فقط. أي أنه أصبح غير مفتوحًا للإنترنت.
</p>

<p>
	لأن المصادقة ما زالت مُعَطَّلة افتراضيا، فإن لدى أي مستخدم على النظام المحلي وصول كامل لقاعدة البيانات. سنُنشِئ مستخدمًا مسؤولًا لتأمين ذلك، ونُفَعِّل المصادقة ونتحقق من ذلك.
</p>

<h3 id="-1-">
	خطوة 1 - إضافة مستخدم مسؤول
</h3>

<p>
	سنتَّصِل بسطر أوامر Mongo لإضافة مستخدم:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>mongo
</pre>

<p>
	تُحذِّر المُخرجات عندما نستخدم سطر أوامر Mongo من أن التحكم بالوصول معطل لقاعدة البيانات وأن وصول القراءة والكتابة للبيانات والإعدادت غير مقيدة. مخرجات تنفيذ الأمرالسابق هي:
</p>

<pre class="ipsCode">
MongoDB shell version v3.4.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.2
Welcome to the MongoDB shell.
For interactive <span class="hljs-keyword">help</span>, <span class="hljs-keyword">type</span> <span class="hljs-string">"help"</span>.
<span class="hljs-keyword">For</span> more comprehensive documentation, see
        <span class="hljs-keyword">http</span>://docs.mongodb.org/
Questions? Try the support <span class="hljs-keyword">group</span>
        <span class="hljs-keyword">http</span>://groups.google.com/<span class="hljs-keyword">group</span>/mongodb-<span class="hljs-keyword">user</span>
<span class="hljs-keyword">Server</span> has <span class="hljs-keyword">startup</span> <span class="hljs-keyword">warnings</span>:
<span class="hljs-number">2017</span><span class="hljs-number">-02</span><span class="hljs-number">-21</span>T19:<span class="hljs-number">10</span>:<span class="hljs-number">42.446</span>+<span class="hljs-number">0000</span> I <span class="hljs-keyword">STORAGE</span>  [initandlisten]
<span class="hljs-number">2017</span><span class="hljs-number">-02</span><span class="hljs-number">-21</span>T19:<span class="hljs-number">10</span>:<span class="hljs-number">42.446</span>+<span class="hljs-number">0000</span> I <span class="hljs-keyword">STORAGE</span>  [initandlisten] ** <span class="hljs-keyword">WARNING</span>: <span class="hljs-keyword">Using</span> the XFS filesystem <span class="hljs-keyword">is</span> strongly recommended <span class="hljs-keyword">with</span> the WiredTiger <span class="hljs-keyword">storage</span> <span class="hljs-keyword">engine</span>
<span class="hljs-number">2017</span><span class="hljs-number">-02</span><span class="hljs-number">-21</span>T19:<span class="hljs-number">10</span>:<span class="hljs-number">42.446</span>+<span class="hljs-number">0000</span> I <span class="hljs-keyword">STORAGE</span>  [initandlisten] **          See <span class="hljs-keyword">http</span>://dochub.mongodb.org/core/prodnotes-filesystem
<span class="hljs-number">2017</span><span class="hljs-number">-02</span><span class="hljs-number">-21</span>T19:<span class="hljs-number">10</span>:<span class="hljs-number">42.534</span>+<span class="hljs-number">0000</span> I CONTROL  [initandlisten]
<span class="hljs-number">2017</span><span class="hljs-number">-02</span><span class="hljs-number">-21</span>T19:<span class="hljs-number">10</span>:<span class="hljs-number">42.534</span>+<span class="hljs-number">0000</span> I CONTROL  [initandlisten] ** <span class="hljs-keyword">WARNING</span>: <span class="hljs-keyword">Access</span> control <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> enabled <span class="hljs-keyword">for</span> the database.
<span class="hljs-number">2017</span><span class="hljs-number">-02</span><span class="hljs-number">-21</span>T19:<span class="hljs-number">10</span>:<span class="hljs-number">42.534</span>+<span class="hljs-number">0000</span> I CONTROL  [initandlisten] **          <span class="hljs-keyword">Read</span> <span class="hljs-keyword">and</span> write <span class="hljs-keyword">access</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">data</span> <span class="hljs-keyword">and</span> configuration <span class="hljs-keyword">is</span> unrestricted.
<span class="hljs-number">2017</span><span class="hljs-number">-02</span><span class="hljs-number">-21</span>T19:<span class="hljs-number">10</span>:<span class="hljs-number">42.534</span>+<span class="hljs-number">0000</span> I CONTROL  [initandlisten]
&gt;
</pre>

<p>
	يمكنك اختيار الاسم الذي تريده للمستخدم المسؤول لأنَّ الصلاحيات تأتي من إعطاء الدور <code>userAdminAnyDatabase</code>. تُحدد قاعدة البيانات <code>admin</code> أين تُخَزَّن بيانات الاعتماد. يمكنك الاطلاع أكثر عن المصادقة في جزء <a href="https://docs.mongodb.com/manual/core/authentication/" rel="external nofollow">مصادقة</a> أمنية MongoDB.
</p>

<p>
	حدد اسم مستخدم وتأكد من اختيار كلمة مرور آمنة واستبدِلهما في الأمر التالي:
</p>

<pre class="ipsCode">
&gt; use admin
&gt; db.createUser(
&gt;   {
&gt;     <span class="hljs-string">user:</span> <span class="hljs-string">"AdminSammy"</span>,
&gt;     <span class="hljs-string">pwd:</span> <span class="hljs-string">"AdminSammy'sSecurePassword"</span>,
&gt;     <span class="hljs-string">roles:</span> [ { <span class="hljs-string">role:</span> <span class="hljs-string">"userAdminAnyDatabase"</span>, <span class="hljs-string">db:</span> <span class="hljs-string">"admin"</span> } ]
&gt;   }
&gt; )
</pre>

<p>
	عند بدء أمر <code>db.createUser</code>، فإن سطر الأوامر سيضع ثلاث نقاط قبل كل سطر حتى انتهاء الأمر. بعد ذلك، يظهر رد بأن المستخدم قد أُنشِئ كالتالي:
</p>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
&gt; use admin
switched to db admin
&gt; db.createUser(
...   {
...     user: <span class="hljs-string">"AdminSammy"</span>,
...     pwd: <span class="hljs-string">"AdminSammy'sSecurePassword"</span>,
...     roles: [ { role: <span class="hljs-string">"userAdminAnyDatabase"</span>, db: <span class="hljs-string">"admin"</span> } ]
...   }
... )
Successfully added user: {
        <span class="hljs-string">"user"</span> : <span class="hljs-string">"AdminSammy"</span>,
        <span class="hljs-string">"roles"</span> : [
                {
                        <span class="hljs-string">"role"</span> : <span class="hljs-string">"userAdminAnyDatabase"</span>,
                        <span class="hljs-string">"db"</span> : <span class="hljs-string">"admin"</span>
                }
        ]
}
</pre>

<p>
	اكتب "exit" ثم اضغط على <code>ENTER</code> أو اضغط على <code>CTRL+C</code> للخروج.
</p>

<p>
	سَيُتاح الآن للمستخدم إدخال بيانات الاعتماد، لكن لن يُطلَب هذا من المستخدام حتى تفعيل المصادقة وإعادة تشغيل برنامج MongoDB الخفي.
</p>

<h3 id="-2-">
	خطوة 2 - تفعيل المصادقة
</h3>

<p>
	المصادقة مفعلة في ملف <code>mongod.conf</code>. عند تفعيلها وإعادة تشغيل <code>mongod</code>، سيظل المستخدمون قادرون على الاتصال ب Mongo بدون مصادقة، لكن سيُطلَب منهم اسم مستخدم وكلمة مرور قبل أي تفاعل.
</p>

<p>
	لنفتح ملف الإعداد:
</p>

<pre class="ipsCode">
$ sudo nano <span class="hljs-regexp">/etc/m</span>ongod.conf
</pre>

<p>
	في الجزء <code>‎#security</code>، ستُزيل التعليق من أمام <code>security</code> لتفعيل المقطع. ثم سنُضيف إعداد المصادقة. يجب أن تبدو الأسطر كما في الأسفل بعد إلغاء تعليقها:
</p>

<ul>
<li>
		الملف mongodb.conf:
	</li>
</ul>
<pre class="ipsCode" id="ips_uid_8170_7">
. . .
<span style="color:red;">security:</span>
<span style="color:red;"> authorization: "enabled"</span>
 . . .
</pre>

<p>
	لاحظ أنَّ سطر "Security" لا يحوي مسافة في بدايته، بينما سطر "authorization" يجب أن يبدأ بِمسافتين.
</p>

<p>
	نُعيد تشغيل البرنامج الخفي بعد حفظ الملف وإغلاقه:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo systemctl restart mongod
</pre>

<p>
	إن أخطأنا في ملف الإعداد فلن يبدأ البرنامج الخفي بالعمل. ولأن <code>systemctl</code> لا تعرض أي مخرجات فَسنستخدم خيار <code>status</code> للتحقق من ذلك:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>sudo systemctl status mongod
</pre>

<p>
	إن ظهر <code>Active: active (running)‎</code> في المخرجات وانتهى بشيء كما يلي، فإن أمر <code>restart</code> قد نُفِّذ بنجاح:
</p>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
<span class="hljs-selector-tag">Jan</span> 23 19<span class="hljs-selector-pseudo">:15</span><span class="hljs-selector-pseudo">:42</span> <span class="hljs-selector-tag">MongoHost</span> <span class="hljs-selector-tag">systemd</span><span class="hljs-selector-attr">[1]</span>: <span class="hljs-selector-tag">Started</span> <span class="hljs-selector-tag">High-performance</span>, <span class="hljs-selector-tag">schema-free</span> <span class="hljs-selector-tag">document-oriented</span> <span class="hljs-selector-tag">database</span>.
</pre>

<p>
	بعد التأكد من أن البرنامج الخفي يعمل، لنُجَرِّب المصادقة.
</p>

<h3 id="-3-">
	خطوة 3 - التحقق من منع المستخدمين غير المخولين
</h3>

<p>
	أولا، نحاول الاتصال بدون معلومات اعتماد للتحقق من أن الدخول ممنوع:
</p>

<pre class="ipsCode">
 <span class="hljs-variable">$ </span>mongo
</pre>

<p>
	تم حل جميع التحذيرات بعد تفعيل المصادقة.
</p>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
MongoDB <span class="hljs-keyword">shell</span> <span class="hljs-keyword">version</span> v3.<span class="hljs-number">4.2</span>
connecting <span class="hljs-keyword">to</span>: mongod<span class="hljs-variable">b:</span>//<span class="hljs-number">127.0</span>.<span class="hljs-number">0.1</span>:<span class="hljs-number">27017</span>
MongoDB server <span class="hljs-keyword">version</span>: <span class="hljs-number">3.4</span>.<span class="hljs-number">2</span>
</pre>

<p>
	اتصلنا بقاعدة بيانات <code>test</code>. سَنتأكد من أن الوصول ممنوع باستخدام الأمر <code>show dbs</code>:
</p>

<pre class="ipsCode">
 &gt; <span class="hljs-keyword">show</span> dbs
</pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
<span class="hljs-number">2017</span>-<span class="hljs-number">02</span>-<span class="hljs-number">21</span>T19:<span class="hljs-number">20</span>:<span class="hljs-number">42.919</span>+<span class="hljs-number">0000</span> E QUERY    [thread1] Error: listDatabases failed:{
        <span class="hljs-string">"ok"</span> : 0,
        <span class="hljs-string">"errmsg"</span> : "<span class="hljs-keyword"><span class="hljs-keyword">not</span></span> <span class="hljs-type">authorized</span> on admin to execute command { listDatabases: <span class="hljs-number">1.0</span> }<span class="hljs-string">",
        "</span>code<span class="hljs-string">" : 13,
        "</span>codeName<span class="hljs-string">" : "</span>Unauthorized<span class="hljs-string">"
 . . .</span>
</pre>

<p>
	لن نتمكن من إنشاء مستخدمين أو تنفيذ أوامر بصلاحيات مشابهة بدون مصادقة.
</p>

<p>
	نُغلِق سطر الأوامر للمتابعة:
</p>

<pre class="ipsCode">
 &gt; <span class="hljs-keyword">exit</span>
</pre>

<p>
	ثانيًا، نتحقق من أن المستخدم المسؤول الذي أنشأناه يمكنه الوصول.
</p>

<h3 id="-4-">
	خطوة 4 - التحقق من إمكانية وصول المستخدم المسؤول
</h3>

<p>
	سَنَتَّصِل باستخدام المستخدم المسؤول الذي أنشأناه باستخدام الخيار <code>‎-u</code> لتزويد اسم المستخدم والخيار <code>‎-p</code> ليطلب كلمة مرور. سنحتاج أيضا إلى تزويد اسم قاعدة البيانات التي خُزِّنَت فيها بيانات اعتماد المستخدم باستخدام الخيار <code>‎--authenticationDatabase</code>.
</p>

<pre class="ipsCode">
 $ mongo -u AdminSammy -<span class="hljs-selector-tag">p</span> --authenticationDatabase admin
</pre>

<p>
	سيُطلب منَّا كلمة المرور، لذلك ندخلها. سننتقل إلى سطر الأوامر عند ادخال كلمة المرور الصحيحة حيث يمكننا تنفيذ الأمر <code>show dbs</code>:
</p>

<p>
	المخرجات
</p>

<pre class="ipsCode">
MongoDB shell version v3<span class="hljs-meta">.4</span><span class="hljs-meta">.2</span>
<span class="hljs-keyword">Enter</span> password:
connecting to: mongodb://<span class="hljs-number">127.0</span><span class="hljs-meta">.0</span><span class="hljs-meta">.1</span>:<span class="hljs-number">27017</span>
MongoDB server version: <span class="hljs-number">3.4</span><span class="hljs-meta">.2</span>

&gt;
</pre>

<p>
	يجب أن نرى قاعدة البيانات بدلًا من رفض الوصول:
</p>

<pre class="ipsCode">
 &gt; <span class="hljs-keyword">show</span> dbs
</pre>

<p>
	المخرجات:
</p>

<pre class="ipsCode">
<span class="hljs-selector-tag">admin</span>  0<span class="hljs-selector-class">.000GB</span>
<span class="hljs-selector-tag">local</span>  0<span class="hljs-selector-class">.000GB</span>
</pre>

<p>
	للخروج، أدخل <code>exit</code> أو اضغط <code>CTRL+C</code>.
</p>

<h2 id="-">
	خاتمة
</h2>

<p>
	ثبَّتنا الآن MongoDB وإجرينا عمليات التهيئة والحماية المطلوبة وتحققنا من عملها. يمكنك الآن بدء استعمالها وأنت مطمئن القلب ومرتاح البال.
</p>

<p>
	يمكنك العثور على المزيد من الدروس المتعمقة في كيفية إعداد واستخدام MongoDB <a href="https://academy.hsoub.com/devops/servers/databases/mongodb" rel="">في هذه المقالات من أكاديمية حسوب</a>. يُعد <a href="https://docs.mongodb.com/v3.2/" rel="external nofollow">التوثيق الرسمي ل MongoDB</a> أيضا مصدر ممتاز للخيارات التي يقدمها MongoDB.
</p>

<p>
	كما يمكنك الاطلاع على توثيق MongoDB لتتعلم أكثر عن <a href="https://docs.mongodb.com/manual/core/authentication/" rel="external nofollow">المصادقة</a>، و<a href="https://docs.mongodb.com/manual/core/authorization/" rel="external nofollow">التحكم بالوصول وفقا للدور</a>، و<a href="https://docs.mongodb.com/manual/tutorial/manage-users-and-roles/" rel="external nofollow">المستخدمون والأدوار</a>.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-18-04" rel="external nofollow">How to Install MongoDB on Ubuntu 18.04</a> لصاحبه الكاتب Mateusz Papiernik.
</p>
]]></description><guid isPermaLink="false">435</guid><pubDate>Sun, 04 Aug 2019 11:09:48 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x646;&#x634;&#x627;&#x621; &#x648;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x646;&#x633;&#x62E; &#x627;&#x644;&#x627;&#x62D;&#x62A;&#x64A;&#x627;&#x637;&#x64A; &#x644;&#x642;&#x648;&#x627;&#x639;&#x62F; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MongoDB &#x639;&#x644;&#x649; &#x646;&#x638;&#x627;&#x645; &#x623;&#x648;&#x628;&#x646;&#x62A;&#x648;</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r276/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/mongodb-backup-ubuntu.png.3f36f36a1a9b2e2089c2ab6de3b14ad8.png" /></p>

<p>
	يختار كثيرون من مطوري الويب الحديث اليوم استخدام قواعد بيانات NoSQL في مشاريعهم، وعادة ما تكون MongoDB اختيارهم الأول.
</p>

<p>
	إنّ إنشاء نسخ احتياطية بشكل دوري أمر مهم إن كنت تستخدم قواعد MongoDB في مشاريع في طور التشغيل وذلك بغرض الحفاظ على البيانات من التلف، ولحسن الحظ، توفّر MongoDB أمرًا بسيطًا ضمن أدواتها لإنشاء واستعادة النسخ الاحتياطية.
</p>

<p>
	لفهم كيفية عمل النسخ الاحتياطية دون المساس بقواعد بيانات عملك الخاص، سنبدأ المقال بإنشاء قاعدة بيانات جديدة وإضافة قدر بسيط من البيانات إليها، بعد ذلك سنقوم بإنشاء نسخة احتياطية لهذه القاعدة، ومن ثم حذفها واستعادتها من النسخة الاحتياطية التي قمنا بإنشائها.
</p>

<p style="text-align: center;">
	<img alt="mongodb-backup-ubuntu.png" class="ipsImage ipsImage_thumbnailed" data-fileid="17892" data-unique="rzp6zntjt" src="https://academy.hsoub.com/uploads/monthly_2016_06/mongodb-backup-ubuntu.png.0881c5353ec89f302394d7c00f2b61f0.png"></p>

<h2>
	المتطلبات
</h2>

<ul>
<li>
		نظام تشغيل Ubuntu 14.04،
	</li>
	<li>
		مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر <span style="font-family:courier new,courier,monospace;">sudo</span>. يمكن مراجعة مقال <a href="https://academy.hsoub.com/devops/servers/%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%A7%D8%A8%D8%AA%D8%AF%D8%A7%D8%A6%D9%8A-%D9%84%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r4/" rel="">الإعداد الابتدائي لخادوم أوبنتو 14.04</a> لمزيد من المعلومات،
	</li>
	<li>
		تثبيت وإعداد MongoDB.
	</li>
</ul>
<h2>
	الخطوة الأولى: إنشاء قاعدة بيانات تجريبية
</h2>

<p>
	إنّ إنشاء نسخة احتياطية لقاعدة بيانات فارغة ليس أمرًا مفيدًا، لذا سنقوم في هذه الخطوة بإنشاء قاعدة بيانات تجريبية وإضافة بعض البيانات لها.
</p>

<p>
	إنّ أسهل طريقة للتعامل مع MongoDB هي عبر سطر أوامرها الذي يمكن فتحه بتنفيذ الأمر <span style="font-family:courier new,courier,monospace;">mongo</span> في سطر الأوامر العادي.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_8">
<span class="pln">&gt; mongo</span></pre>

<p>
	بعد ذلك سنقوم بإنشاء قاعدة بيانات جديدة سندعوها <span style="font-family:courier new,courier,monospace;">myDatabase</span> وذلك باستخدام الأمر المساعد <span style="font-family:courier new,courier,monospace;">use</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_10">
<span class="pln">$ use myDatabasee</span></pre>

<p>
	سنحصل على الخرج التالي نتيجة لتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_12">
<span class="pln">switched to db myDatabase</span></pre>

<p>
	ينبغي على جميع البيانات في قاعدة MongoDB أن تتبع لمجموعة collection. وبالرغم من ذلك، فليس هناك حاجة لإنشاء مجموعة بشكل خاص، فعند استخدام التابع <span style="font-family:courier new,courier,monospace;">insert</span> لإدخال بيانات لمجموعة غير موجودة، سيتم إنشاء المجموعة بشكل تلقائي قبل كتابة البيانات.
</p>

<p>
	بإمكانك استخدام الشفرة البرمجية التالية لإضافة 3 سندات documents لمجموعة تدعى <span style="font-family:courier new,courier,monospace;">myCollection</span> باستخدام التابع <span style="font-family:courier new,courier,monospace;">insert</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_15">
<span class="pln">db.myCollection.insert([
    {'name': 'Alice', 'age': 30},
    {'name': 'Bill', 'age': 25},
    {'name': 'Bob', 'age': 35}
]);</span></pre>

<p>
	وستظهر الرسالة التالية إن تم تنفيذ الشفرة بنجاح:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_17">
<span class="pln">BulkWriteResult({
    "writeErrors" : [ ],
    "writeConcernErrors" : [ ],
    "nInserted" : 3,
    "nUpserted" : 0,
    "nMatched" : 0,
    "nModified" : 0,
    "nRemoved" : 0,
    "upserted" : [ ]
})</span></pre>

<h2>
	الخطوة الثانية: التحقق من حجم قاعدة البيانات
</h2>

<p>
	الآن وبعد أن حصلنا على قاعدة مع بعض البيانات فيها، سنقوم بأخذ نسخة احتياطية لها. ولكن حجم النسخ الاحتياطية قد يكون كبيرًا إن كانت لديك قاعدة بيانات كبيرة، وبالتالي حتى نتجنب المخاطرة باستهلاك مساحة التخزين المتبقية في القرص، وبالنتيجة إبطاء الخادوم أو منعه من العمل، فيجب أن نتحقق من حجم قاعدة البيانات قبل البدء بالنسخ الاحتياطي.
</p>

<p>
	للقيام بذلك بإمكاننا استخدام التابع stats والتحقق من القيمة التي يعيدها المفتاح <span style="font-family:courier new,courier,monospace;">dataSize</span> لمعرفة حجم القاعدة مقدّرًا بالبايت.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_19">
<span class="pln">$ db.stats().dataSize;</span></pre>

<p>
	وبالنسبة لقاعدة بياناتنا التجريبية فإن الحجم سيكون رقمًا صغيرًا يبلغ 592 بايت.
</p>

<p>
	انتبه إلى أن القيمة التي يعطيها <span style="font-family:courier new,courier,monospace;">dataSize</span> هي قيمة تقريبية لحجم النسخة الاحتياطية.
</p>

<h2>
	الخطوة الثالثة: إنشاء النسخة الاحتياطية
</h2>

<p>
	بإمكاننا استخدام الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span> والذي سيقوم باستدعاء أداة من الأدوات المرفقة مع MongoDb.
</p>

<p>
	سيقوم الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span> بشكل افتراضي بإنشاء نسخة احتياطية لجميع قواعد البيانات المستخدمة. ولإنشاء نسخة احتياطية لقاعدة بيانات معيّنة، يجب إضافة الخيار -d وتحديد اسم القاعدة. إضافة لذلك، يمكن إعلام <span style="font-family:courier new,courier,monospace;">mongodump</span> بالمكان الذي نرغب بتخزين النسخة الاحتياطية فيه وذلك باستخدام الخيار -o وتحديد المسار.
</p>

<p>
	يتم تنفيذ <span style="font-family:courier new,courier,monospace;">mongodump</span> من سطر الأوامر العادي لذا سنقوم الآن بإنهاء العمل بسطر أوامر <span style="font-family:courier new,courier,monospace;">mongo</span> والعودة لسطر الأوامر العادي وذلك بالضغط على مفتاحي <span style="font-family:courier new,courier,monospace;">Ctrl+D</span>.
</p>

<p>
	سنقوم بعد ذلك بتنفيذ الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span> لإنشاء نسخة احتياطية لقاعدتنا <span style="font-family:courier new,courier,monospace;">myDatabase</span> وتخزين النسخة في المسار <span style="font-family:courier new,courier,monospace;">backups/first_backup/~</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_21">
<span class="pln">$ mongodump -d myDatabase -o ~/backups/first_backup</span></pre>

<p>
	إن تم تنفيذ الأمر بنجاح فيفترض أن تظهر الرسالة التالية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_23">
<span class="pln">2015-11-24T18:11:58.590-0500  writing myDatabase.myCollection to /home/me/backups/first_backup/myDatabase/myCollection.bson
2015-11-24T18:11:58.591-0500  writing myDatabase.myCollection metadata to /home/me/backups/first_backup/myDatabase/myCollection.metadata.json
2015-11-24T18:11:58.592-0500  done dumping myDatabase.myCollection (3 documents)
2015-11-24T18:11:58.592-0500  writing myDatabase.system.indexes to /home/me/backups/first_backup/myDatabase/system.indexes.bson</span></pre>

<p>
	لاحظ بأنّ النسخة الاحتياطية ليست ملفًّا واحدًا بل هو مجلد يملك الهيكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_25">
<span class="pln">first_backup
└── myDatabase
    ├── myCollection.bson
    ├── myCollection.metadata.json
    └── system.indexes.bson</span></pre>

<h2>
	الخطوة الرابعة: حذف قاعدة البيانات
</h2>

<p>
	لاختبار النسخة الاحتياطية التي قمنا بالحصول عليها، يمكن إما التوجّه لخادوم آخر يملك نسخة MongoDB أخرى أو حذف قاعدة البيانات التجريبية من الخادوم الحالي، وسنختار الخيار الثاني في المقال.
</p>

<p>
	لنقم الآن بفتح سطر أوامر <span style="font-family:courier new,courier,monospace;">mongo</span> ومن ثم الاتصال بقاعدة البيانات:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_27">
<span class="pln">$ mongo myDatabase</span></pre>

<p>
	سنقوم بحذف قاعدة البيانات باستخدام التابع <span style="font-family:courier new,courier,monospace;">dropDatabase</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_29">
<span class="pln">$ db.dropDatabase();</span></pre>

<p>
	إن تم حذف القاعدة بنجاح، ستشاهد الرسالة التالية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_31">
<span class="pln">{ "dropped" : "myDatabase", "ok" : 1 }</span></pre>

<p>
	وللتأكد يمكن استخدام التابع <span style="font-family:courier new,courier,monospace;">find</span> على المجموعة <span style="font-family:courier new,courier,monospace;">myCollection</span> وسنرى بأن جميع البيانات المدخلة سابقًا قد اختفت.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_33">
<span class="pln">$ db.myCollection.find();</span></pre>

<p>
	وبطبيعة الحال فلن يكون هناك أي خرج نتيجة لتنفيذ الأمر لعدم وجود بيانات لإظهارها.
</p>

<h2>
	الخطوة الخامسة: استعادة قاعدة البيانات من النسخة الاحتياطية
</h2>

<p>
	لاستعادة قاعدة البيانات التي حصلنا على نسخة احتياطية منها باستخدام الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span>، سنقوم باستخدام أداة أخرى من أدوات Mongo يسمى <span style="font-family:courier new,courier,monospace;">mongorestore</span>، ولكن قبل استخدامه قم بالعودة لسطر الأوامر العادي بالنقر على مفتاحي<span style="font-family:courier new,courier,monospace;"> Ctrl+D</span> إن كنت ما تزال في سطر أوامر <span style="font-family:courier new,courier,monospace;">mongo</span>.
</p>

<p>
	إن من السهل استخدام أمر <span style="font-family:courier new,courier,monospace;">mongorestore</span> حيث يكفي تمرير المسار الذي توجد به النسخة الاحتياطية كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_35">
<span class="pln">$ mongorestore ~/backups/first_backup/</span></pre>

<p>
	وستظهر رسالة تشبه التالية دلالة على نجاح التنفيذ:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_37">
<span class="pln">2015-11-24T18:27:04.250-0500  building a list of dbs and collections to restore from /home/me/backups/first_backup/ dir
2015-11-24T18:27:04.251-0500  reading metadata file from /home/me/backups/first_backup/myDatabase/myCollection.metadata.json
2015-11-24T18:27:04.252-0500  restoring myDatabase.myCollection from file /home/me/backups/first_backup/myDatabase/myCollection.bson
2015-11-24T18:27:04.309-0500  restoring indexes for collection myDatabase.myCollection from metadata
2015-11-24T18:27:04.310-0500  finished restoring myDatabase.myCollection (3 documents)
2015-11-24T18:27:04.310-0500  done</span></pre>

<p>
	ولاختبار البيانات التي قمنا باستعادتها، سنقوم بفتح سطر أوامر <span style="font-family:courier new,courier,monospace;">mongo</span> مجددًا والاتصال بقاعدة <span style="font-family:courier new,courier,monospace;">myDatabase</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_39">
<span class="pln">$ mongo myDatabase</span></pre>

<p>
	ومن ثم نستخدم الأمر <span style="font-family:courier new,courier,monospace;">find</span> على المجموعة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_41">
<span class="pln">$ db.myCollection.find();</span></pre>

<p>
	فإن سار كل شيء على ما يرام، ينبغي الآن أن تظهر لك البيانات المدخلة سابقًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9605_43">
<span class="pln">{ "_id" : ObjectId("5654e76f21299039c2ba8720"), "name" : "Alice", "age" : 30 }
{ "_id" : ObjectId("5654e76f21299039c2ba8721"), "name" : "Bill", "age" : 25 }
{ "_id" : ObjectId("5654e76f21299039c2ba8722"), "name" : "Bob", "age" : 35 }</span></pre>

<h2>
	الخلاصة
</h2>

<p>
	تعلّمنا كيفية استخدام <span style="font-family:courier new,courier,monospace;">mongodump</span> و <span style="font-family:courier new,courier,monospace;">mongorestore</span> لإنشاء نسخة احتياطية واستعادة واحدة تخص قاعدة بيانات MongoDB.
</p>

<p>
	تذكر بأن إنشاء نسخة احتياطية هي عملية شرهة لموارد النظام ويمكن لها أن تخفض من أداء محرك MongoDB، لذا ينصح بأن تتم العملية فقط في الساعات التي تكون فيها الطلبات على القاعدة أقل ما يمكن.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-create-and-use-mongodb-backups-on-ubuntu-14-04" rel="external nofollow">How to Create and Use MongoDB Backups on Ubuntu 14.04</a> لصاحبته Hazel Virdó.
</p>
]]></description><guid isPermaLink="false">276</guid><pubDate>Tue, 21 Jun 2016 12:12:29 +0000</pubDate></item><item><title>&#x627;&#x644;&#x646;&#x633;&#x62E; &#x627;&#x644;&#x627;&#x62D;&#x62A;&#x64A;&#x627;&#x637;&#x64A;&#x60C; &#x627;&#x633;&#x62A;&#x639;&#x627;&#x62F;&#x629; &#x648;&#x646;&#x642;&#x644; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MongoDB &#x639;&#x644;&#x649; &#x646;&#x638;&#x627;&#x645; &#x62A;&#x634;&#x63A;&#x64A;&#x644; &#x623;&#x648;&#x628;&#x646;&#x62A;&#x648;</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A%D8%8C-%D8%A7%D8%B3%D8%AA%D8%B9%D8%A7%D8%AF%D8%A9-%D9%88%D9%86%D9%82%D9%84-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r267/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/backup-migrate-mongodb.png.da6840783093c06f17cabf7705e87301.png" /></p>

<p>
	يُعدّ محرك قواعد بيانات MongoDB أحد أشهر محرّكات قواعد بيانات NoSQL، ويشتهر بمرونته وقابليته للتوسعة وقوّته ومدى اعتماديّته وسهولة استخدامه. سنتحدث في المقال عن كيفية إجراء نسخ احتياطي واستعادة نسخة احتياطية ونقل قاعدة بيانات MongoDB.
</p>

<p>
	عند الحديث عن <a href="https://academy.hsoub.com/devops/servers/databases/%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D9%88%D8%AA%D8%B5%D8%AF%D9%8A%D8%B1-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D9%81%D9%8A-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r265/" rel="">الاستيراد والتصدير في MongoDB</a> فالمقصود التعامل مع البيانات بصيغة مقروءة من قبل البشر، ومتوافقة مع باقي المنتجات البرمجية. بالمقابل، فإن عمليات النسخ الاحتياطي واستعادة النسخ الاحتياطية تُنشئ أو تَستخدم نمط بيانات ثنائية binary خاصّة بـ MongoDB، وتحافظ بالتالي على تناسق وسلامة البيانات إضافة إلى سمات MongoDB الخاصة.
</p>

<p>
	بناء على ما سبق، فإنّه من المفضّل استخدام النسخ الاحتياطي عند الحاجة لتهجير migration قاعدة البيانات طالما أن هناك توافقية ما بين النظام المصدر والنظام الهدف.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17691" data-unique="hoc83l0pr" src="https://academy.hsoub.com/uploads/monthly_2016_06/backup-migrate-mongodb.png.fbe3cbecc8144f3dbc4267399587b6b7.png" alt="backup-migrate-mongodb.png"></p>

<h2>
	المتطلبات الأولية
</h2>

<p>
	قبل أن نتابع، يرجى التأكّد من توفر المتطلبات التالية بشكل كامل:
</p>

<ul>
<li>
		نظام تشغيل Ubuntu،
	</li>
	<li>
		مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر <span style="font-family:courier new,courier,monospace;">sudo</span>. يمكن مراجعة مقال <a href="https://academy.hsoub.com/devops/servers/%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%A7%D8%A8%D8%AA%D8%AF%D8%A7%D8%A6%D9%8A-%D9%84%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r4/" rel="">الإعداد الابتدائي لخادوم أوبنتو 14.04</a> لمزيد من المعلومات،
	</li>
	<li>
		تثبيت وإعداد MongoDB.
	</li>
	<li>
		وعدا عمّا قد يستثنى بوضوح، فإنّ جميع الأوامر التي تحتاج لصلاحيات مدير نظام root في المقال، يجب أن يتم تنفيذها من قبل مستخدم عادي يملك صلاحيات sudo.
	</li>
	<li>
		نسخة قاعدة بيانات MongoDB تجريبية، ويمكن الحصول على واحدة وتثبيتها وفق التعليمات المذكورة في مقال <a href="https://academy.hsoub.com/devops/servers/databases/%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D9%88%D8%AA%D8%B5%D8%AF%D9%8A%D8%B1-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D9%81%D9%8A-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r265/" rel="">استيراد وتصدير قاعدة بيانات MongoDB في نظام أوبنتو 14.04</a>.
	</li>
</ul>
<p>
	<strong>تنبيه</strong>: يجب تنفيذ جميع الأوامر المذكورة في المقال بصلاحيات المستخدم العادي من خلال أمر <span style="font-family:courier new,courier,monospace;">sudo</span> ويستثنى من ذلك ما يذكر صراحة أن يتم تنفيذه وفق صلاحيات مدير النظام root.
</p>

<h2>
	فهم الأساسيات
</h2>

<p>
	سنحتاج لفهم بعض الأمور قبل أن نتابع أكثر في المقال، وإن كنت تملك بعض الخبرة مع قواعد البيانات العلائقية relational المشهورة مثل MySQL، فربّما تجد بعض التشابه عند العمل مع MongoDB.
</p>

<p>
	إنّ أول ما تحتاج معرفته حول MongoDB هو أنها تستخدم صيغتي json و bson (الصيغة الثنائية binary من json) بغرض تخزين المعلومات. إنّ Json هي صيغة مقروءة من قبل البشر وبالتالي مناسبة جدًا لتصدير واستيراد البيانات في نهاية الأمر، ومن الممكن أيضًا التعديل على البيانات المصدّرة باستخدام أيّ أداة تدعم json، بما في ذلك أي محرر نصوص بسيط.
</p>

<p>
	يبدو أحد الأمثلة عن مستند json على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_10">
<span class="pln">{"address":[
	{"building":"1007", "street":"Park Ave"},
	{"building":"1008", "street":"New Ave"},
]}</span></pre>

<p>
	إنّ Json مناسبة جدًا للعمل معها، لكنها لا تدعم جميع أنماط البيانات المتاحة في bson، وهذا يعني بأنّه سيكون لدينا "فقدان في الدقّة" في البيانات عند استخدام json، ولهذا السبب فإنّه من الأفضل استخدام الصيغة الثنائية bson في حالة النسخ الاحتياطي والاستعادة لأنّها ستساعد في استعادة قاعدة بيانات MongoDB بشكل أدق.
</p>

<p>
	ثانيًا، ليس هناك داعٍ للقلق حول إنشاء قاعدة البيانات إن لم تكن موجودة أصلًا عند القيام باستعادة نسخة احتياطية، حيث سيتم إنشاؤها بشكل تلقائي. إضافة لذلك، فإنّ هيكل المجموعات collections (التي تُقابل الجداول) في القاعدة -بخلاف محركات قواعد البيانات الأخرى- سيتم إنشاؤها أيضًا بشكل تلقائي عند إدراج insert أول سطر.
</p>

<p>
	ثالثًا، إن قراءة وإدراج كمّية كبيرة من البيانات في MongoDB، قد يستهلك مصادر النظام كقدرة المعالج، الذاكرة ومساحة التخزين بشكل كبير جدًا وهذه نقطة حساسة على اعتبار أن MongoDB تُستخدم عادة مع قواعد البيانات الكبيرة والبيانات الضخمة، والحل الأسهل لهذه المشكلة هو تنفيذ عمليات التصدير والنسخ الاحتياطي ليلًا.
</p>

<p>
	رابعًا، فقد يكون هناك مشكلة في تناسق البيانات إن كنت تملك خادوم MongoDB معرّض لضغط العمل باستمرار وبالتالي قد تتغير البيانات أثناء عملية التصدير، حيث لا يوجد حل بسيط لهذه المشكلة ولكن في نهاية المقال سنتحدث حول استنساخ البيانات replication.
</p>

<p>
	وعلى الرغم من أنه من الممكن استخدام وظائف الاستيراد والتصدير للحصول على نسخة احتياطية أو استعادتها، تبقى هناك طرق أفضل لتضمن دقة البيانات في قاعدة MongoDB، ومن هذه الطرق استخدام الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span> للحصول على نسخة احتياطية للبيانات، والأمر <span style="font-family:courier new,courier,monospace;">mongorestore</span> لاستعادة نسخة احتياطية سابقة.
</p>

<h2>
	الحصول على نسخة احتياطية لقاعدة بيانات MongoDB
</h2>

<p>
	لنتحدث أولًا عن الحصول على نسخة احتياطية لقاعدة البيانات.
</p>

<p>
	يقوم المُعامل<span style="font-family:courier new,courier,monospace;"> db-- </span>في الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span> بتحديد اسم قاعدة البيانات التي نرغب بالحصول على نسخة احتياطية لها، فإن لم يتم تحديد اسم قاعدة البيانات، سيقوم الأمر بإنشاء نسخة احتياطية لجميع قواعد البيانات التي يديرها محرّك MongoDB.
</p>

<p>
	أما لتحديد مسار المجلّد الذي سيتم تخزين النسخ الاحتياطية فيه فنستخدم المُعامل <span style="font-family:courier new,courier,monospace;">out--</span>.
</p>

<p>
	لنرى المثال التالي للحصول على نسخة احتياطية من قاعدة بيانات اسمها <span style="font-family:courier new,courier,monospace;">newdb</span> ولتخزين النسخة في مجلد <span style="font-family:courier new,courier,monospace;">var/backups/mongobackups/</span>.
</p>

<p>
	<strong>نصيحة</strong>: من الأفضل أن يتم تخزين كل نسخة احتياطية في مجلد فرعي يُسمّى بتاريخ اليوم الذي تم إنشاء النسخة الاحتياطية فيه، مثل <span style="font-family:courier new,courier,monospace;">var/backups/mongobackups/01-20-16/ </span>(العشرون من كانون الثاني 2016).
</p>

<p>
	لنقم أولًا بإنشاء المجلد الرئيسي الذي سنقوم فيه بتخزين النسخ الاحتياطية لقواعد MongoDB التي نملكها، ونستخدم لذلك الأمر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_12">
<span class="pln">$ sudo mkdir /var/backups/mongobackups</span></pre>

<p>
	ثم نقوم بإنشاء نسخة احتياطية بالأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_14">
<span class="pln">$ sudo mongodump --db newdb --out /var/backups/mongobackups/`date +"%m-%d-%y"`</span></pre>

<p>
	فإن تم تنفيذ الأمر بنجاح، سيظهر ما يشبه النتيجة التالية على الشاشة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_16">
<span class="pln">2016-01-20T10:11:57.685-0500 	writing newdb.restaurants to /var/backups/mongobackups/01-20-16/newdb/restaurants.bson
2016-01-20T10:11:57.907-0500 	writing newdb.restaurants metadata to /var/backups/mongobackups/01-20-16/newdb/restaurants.metadata.json
2016-01-20T10:11:57.911-0500 	done dumping newdb.restaurants (25359 documents)
2016-01-20T10:11:57.911-0500 	writing newdb.system.indexes to /var/backups/mongobackups/01-20-16/newdb/system.indexes.bson</span></pre>

<p>
	لاحظ في الأمر الذي قمنا بتنفيذه أننا أدرجنا الجزء التالي <span style="font-family:courier new,courier,monospace;">"date +"%m-%d-%y</span> الذي يقوم بالحصول على تاريخ اليوم بشكل تلقائي، وبالتالي نحصل على نسخة احتياطية داخل مجلد فرعي <span style="font-family:courier new,courier,monospace;">/var/backups/mongobackups/01-20-16/</span>، وهذا مناسب جدًا إن قمنا بجدولة الأمر ليتم تنفيذه بصورة اوتوماتيكية.
</p>

<p>
	عند الوصول إلى هذه المرحلة نكون قد حصلنا على نسخة احتياطية لقاعدة البيانات المسمّاة <span style="font-family:courier new,courier,monospace;">newdb</span> في المسار <span style="font-family:courier new,courier,monospace;">/var/backups/mongobackups/01-20-16/newdb/</span>، وتملك هذه النسخة جميع المعلومات اللازمة لاستعادة حالة القاعدة <span style="font-family:courier new,courier,monospace;">newdb</span> في حال حصول مشكلة فيها.
</p>

<p>
	وكقاعدة عامة، يجب أن يتم الحصول على نسخ احتياطية بشكل دوري، على أساس نسخة احتياطية يومية مثلًا، ويستحسن أن يتم تنفيذ العملية في الوقت الذي يكون نشاط الخادوم أقل ما يمكن، وللقيام بذلك يمكن جدولة تنفيذ الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span> باستخدام cron حتى يتم تنفيذه بصورة دورية، مثلاً، الساعة 3:03 صباحًا من كل يوم. لتنفيذ ذلك سنقوم بفتح محرّر cron المسمّى <span style="font-family:courier new,courier,monospace;">crontab</span> على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_18">
<span class="pln">$ sudo crontab -e</span></pre>

<p>
	<strong>ملاحظة</strong>: عندما يتم تنفيذ الأمر <span style="font-family:courier new,courier,monospace;">sudo crontab</span> فإننا نقوم بتحرير المهام المجدولة الخاصة بحساب المستخدم مدير النظام root. إن هذا مستحسن لأنه في حال جدولة الأمر <span style="font-family:courier new,courier,monospace;">mongodump</span> ليتم تنفيذه بصلاحيات مستخدم آخر فقد لا يتم التنفيذ بشكل صحيح وخصوصًا إن كانت إعدادات <span style="font-family:courier new,courier,monospace;">sudo</span> تتطلب تأكيد الأمر بإدخال كلمة المرور.
</p>

<p>
	سنقوم في <span style="font-family:courier new,courier,monospace;">crontab</span> بإدخال السطر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_20">
<span class="pln">3 3 * * * mongodump --out /var/backups/mongobackups/`date +"%m-%d-%y"`</span></pre>

<p>
	لاحظ أننا لم نستخدم المعامل <span style="font-family:courier new,courier,monospace;">db-- </span>في الأمر السابق لأننا نرغب بالحصول على نسخة احتياطية دورية لجميع القواعد التي نملكها.
</p>

<p>
	إن تنفيذ النسخ الاحتياطي الدوري سيؤدي مع الوقت إلى استهلاك مساحة التخزين على القرص الصلب، لذا فمن الأفضل أن يتم حذف النسخ الاحتياطية القديمة بصورة دورية أو خفض المساحة التي تستهلكها عبر ضغطها.
</p>

<p>
	لحذف النسخ الاحتياطية التي تم الحصول عليها قبل 7 أيام يمكن أن نستخدم الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_22">
<span class="pln">$ find /var/backups/mongobackups/ -mtime +7 -exec rm -rf {} \;</span></pre>

<p>
	وكما في الأمر المُجدول السابق فمن الممكن التخلص من النسخ الاحتياطية القديمة بصورة دورية عبر تنفيذ الأمر قبل أمر النسخ الاحتياطي، ولأجل هذا سنقوم بإدراج السطر التالي في cron، والذي سيتم تنفيذه الساعة 3:01 صباحًا من كل يوم:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_24">
<span class="pln">3 1 * * * find /var/backups/mongobackups/ -mtime +7 -exec rm -rf {} \;</span></pre>

<p>
	وبإتمام الخطوات السابقة نكون قد ضمنّا حلًا مناسبًا للنسخ الاحتياطي لقواعد بيانات MongoDB.
</p>

<h2>
	استعادة نسخة احتياطية لقاعدة بيانات MongoDB
</h2>

<p>
	إن استعادة نسخة احتياطية سابقة لقاعدة بيانات MongoDB (كالتي حصلنا عليها من الخطوة السابقة) تتم باستخدام الأمر <span style="font-family:courier new,courier,monospace;">mongorestore</span> والذي يمكّنك من الحصول على نسخة مطابقة تمامًا لبيانات القاعدة كما كانت في لحظة إنشاء النسخة الاحتياطية، متضمنًا ذلك جميع الفهارس وأنماط البيانات، وهذه مسألة مفيدة جدًا إن رغبت بنقل قاعدة البيانات.
</p>

<p>
	ومتابعة من المثال السابق، لنرى كيف من الممكن استعادة نسخة احتياطية سابقة.
</p>

<p>
	سنقوم باستخدام المُعامل <span style="font-family:courier new,courier,monospace;">db-- </span>مع الأمر <span style="font-family:courier new,courier,monospace;">mongorestore</span> لتحديد القاعدة التي نرغب باستعادة النسخة الاحتياطية إليها، كما سنستخدم المُعامل <span style="font-family:courier new,courier,monospace;">drop--</span> كي نضمن أن يتم حذف القاعدة القديمة حتى تتم استعادة النسخة الاحتياطية إلى نسخة جديدة من القاعدة لا تحتوي أي مشاكل، وأخيرًا سنقوم بتحديد مسار النسخة الاحتياطية التي نرغب باستعادتها; سيظهر الأمر كاملًا على النحو التالي (لا تنس استبدال المسار بمسار النسخة الموجودة لديك والتي ترغب باستعادتها):
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_26">
<span class="pln">$ sudo mongorestore --db newdb --drop /var/backups/mongobackups/01-20-16/newdb/</span></pre>

<p>
	وسيظهر ما يشبه الخرج التالي على الشاشة في حال تنفيذ الأمر بالشكل الصحيح:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7627_28">
<span class="pln">2016-01-20T10:44:47.876-0500 	building a list of collections to restore from /var/backups/mongobackups/01-20-16/newdb/ dir
2016-01-20T10:44:47.908-0500 	reading metadata file from /var/backups/mongobackups/01-20-16/newdb/restaurants.metadata.json
2016-01-20T10:44:47.909-0500 	restoring newdb.restaurants from file /var/backups/mongobackups/01-20-16/newdb/restaurants.bson
2016-01-20T10:44:48.591-0500 	restoring indexes for collection newdb.restaurants from metadata
2016-01-20T10:44:48.592-0500 	finished restoring newdb.restaurants (25359 documents)
2016-01-20T10:44:48.592-0500 	done</span></pre>

<p>
	وفي هذه الحالة نكون قد أنجزنا استعادة نسخة احتياطية للقاعدة على الخادوم ذاته.
</p>

<p>
	أمّا لو رغبنا بنقل البيانات من خادوم لآخر باستخدام نفس الطريقة، فكُل ما نحتاجه هو نسخ مجلد النسخة الاحتياطية <span style="font-family:courier new,courier,monospace;">/var/backups/mongobackups/01-20-16/newdb/</span> إلى الخادوم الجديد قبل تنفيذ أمر استعادة النسخة الاحتياطية على الخادوم الجديد.
</p>

<h2>
	الخلاصة
</h2>

<p>
	تعرّفنا في المقال على أساسيات إدارة بيانات قاعدة MongoDB فيما يخص النسخ الاحتياطي والاستعادة من نسخة احتياطية سابقة، ونقل قاعدة البيانات من خادوم لآخر.
</p>

<p>
	إن آلية النسخ المُتماثل للبيانات ليست مهمّة بغرض قابلية التوسعة فحسب، وإنما مهمّة للموضوع الذي نتحدث عنه الآن، حيث تسمح الآلية باستمرارية تشغيل خدمة MongoDB دون توقّف أو انقطاع من خلال خادوم MongoDB ثانوي بينما يتم استعادة نسخة احتياطية على الخادوم الرئيسي في حال حدوث خلل ما فيه. وتعتبر سجلّات التشغيل (operations log (oplog جزءًا من آلية النسخة المُتماثل، حيث تقوم هذه السجلّات بتخزين جميع العمليات التي قامت بتغيير البيانات، ومن الممكن استخدام هذا السجل -كما يستخدم السجل الثنائي binary log في MySQL- بغرض استعادة البيانات بعد آخر نسخة احتياطية. تذكّر بأن النسخ الاحتياطي عادة يتم في فترة متأخرة من الليل، فإن قررت استعادة نسخة احتياطية ليلًا (قبل أن تبدأ عملية النسخ الاحتياطي) فستفقد جميع البيانات الجديدة التي لم يتم الحصول على نسخة احتياطية لها أولًا.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-back-up-restore-and-migrate-a-mongodb-database-on-ubuntu-14-04" rel="external nofollow">How To Back Up, Restore, and Migrate a MongoDB Database on Ubuntu 14.04</a> لصاحبه Anatoliy Dimitrov.
</p>
]]></description><guid isPermaLink="false">267</guid><pubDate>Fri, 10 Jun 2016 12:06:43 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x64A;&#x631;&#x627;&#x62F; &#x648;&#x62A;&#x635;&#x62F;&#x64A;&#x631; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MongoDB &#x641;&#x64A; &#x646;&#x638;&#x627;&#x645; &#x623;&#x648;&#x628;&#x646;&#x62A;&#x648; 14.04</title><link>https://academy.hsoub.com/devops/servers/databases/mongodb/%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D9%88%D8%AA%D8%B5%D8%AF%D9%8A%D8%B1-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mongodb-%D9%81%D9%8A-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r265/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/import-export-mongodb.png.618bf5c47d1dfd793f120f35e5d7481c.png" /></p>

<p>
	يُعدّ MongoDB أحد أشهر محركات قواعد البيانات من نوع NoSQL، فهو شهير بمرونته، فعاليّته، موثوقيته وسهولة استخدامه، وسنستعرض في المقال كيفية استيراد وتصدير قواعد بيانات MongoDB.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17688" data-unique="xtzwmcgt2" src="https://academy.hsoub.com/uploads/monthly_2016_06/import-export-mongodb.png.5ea2ed069df7d3e7305a8ced4f7b64d1.png" alt="import-export-mongodb.png"></p>

<p>
	تجدر الإشارة إلى أنّه عند حديثنا عن الاستيراد والتصدير فالمقصود التعامل مع البيانات بصيغة مقروءة من قبل البشر، ومتوافقة مع باقي المنتجات البرمجية. بالمقابل، فإن عمليات النسخ الاحتياطي واستعادة النسخ الاحتياطية تُنشئ أو تَستخدم نمط بيانات ثنائية binary خاصّة بـ MongoDB، وتحافظ بالتالي على تناسق وسلامة البيانات إضافة إلى سمات MongoDB الخاصة.
</p>

<p>
	بناء على ما سبق، فإنّه من المفضّل استخدام النسخ الاحتياطي عند الحاجة لنقل/تهجير migration قاعدة البيانات طالما أن هناك توافقية ما بين النظام المصدر والنظام الهدف، وهذا الموضوع خارج إطار حديثنا.
</p>

<h2>
	المتطلبات الأولية
</h2>

<p>
	قبل أن نتابع، يرجى التأكّد من توفر المتطلبات التالية بشكل كامل:
</p>

<ul>
<li>
		نظام تشغيل Ubuntu 14.04،
	</li>
	<li>
		مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر <span style="font-family:courier new,courier,monospace;">sudo</span>. يمكن مراجعة <a href="https://academy.hsoub.com/devops/servers/%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%A7%D8%A8%D8%AA%D8%AF%D8%A7%D8%A6%D9%8A-%D9%84%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r4/" rel="">الإعداد الابتدائي لخادوم أوبنتو 14.04</a> لمزيد من المعلومات،
	</li>
	<li>
		تثبيت وإعداد MongoDB.
	</li>
</ul>
<p>
	وعدا عمّا قد يستثنى بوضوح، فإنّ جميع الأوامر التي تحتاج لصلاحيات مدير نظام root في المقال، يجب أن يتم تنفيذها من قبل مستخدم عادي يملك صلاحيات <span style="font-family:courier new,courier,monospace;">sudo</span>.
</p>

<h2>
	فهم الأساسيات
</h2>

<p>
	سنحتاج لفهم بعض الأمور قبل أن نتابع المقال، وإن كنت تملك بعض الخبرة مع قواعد البيانات العلائقية relational المشهورة مثل MySQL، فربّما تجد بعض التشابه عند العمل مع MongoDB.
</p>

<p>
	إنّ أول ما تحتاج معرفته حول MongoDB هو أنها تستخدم صيغتي json و bson (الصيغة الثنائية binary من json) بغرض تخزين المعلومات. إنّ Json هي صيغة مقروءة من قبل البشر وبالتالي مناسبة جدًا لتصدير واستيراد البيانات في نهاية الأمر، ومن الممكن أيضًا التعديل على البيانات المصدّرة باستخدام أيّ أداة تدعم json، بما في ذلك أي محرر نصوص بسيط.
</p>

<p>
	يبدو أحد الأمثلة عن مستند json على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_9">
<span class="pln">{"address":[
	{"building":"1007", "street":"Park Ave"},
	{"building":"1008", "street":"New Ave"},
]}</span></pre>

<p>
	إنّ Json مناسبة جدًا للعمل معها، لكنها لا تدعم جميع أنماط البيانات المتاحة في bson، وهذا يعني بأنّه سيكون لدينا "فقدان في الدقّة" في البيانات عند استخدام json، ولهذا السبب فإنّه من الأفضل استخدام الصيغة الثنائية bson في حالة النسخ الاحتياطي والاستعادة لأنّها ستساعد في استعادة قاعدة بيانات MongoDB بشكل أدق.
</p>

<p>
	ثانيًا، ليس هناك داعٍ للقلق حول إنشاء قاعدة البيانات إن لم تكن موجودة أصلًا عند القيام باستعادة نسخة احتياطية، حيث سيتم إنشاؤها بشكل تلقائي. إضافة لذلك، فإنّ هيكل المجموعات collections (التي تُقابل الجداول) في القاعدة -بخلاف محركات قواعد البيانات الأخرى- سيتم إنشاؤها أيضًا بشكل تلقائي عند إدراج insert أول سطر.
</p>

<p>
	ثالثًا، إن قراءة وإدراج كمّية كبيرة من البيانات في MongoDB، قد يستهلك مصادر النظام كقدرة المعالج، الذاكرة ومساحة التخزين بشكل كبير جدًا وهذه نقطة حساسة على اعتبار أن MongoDB تُستخدم عادة مع قواعد البيانات الكبيرة والبيانات الضخمة، والحل الأسهل لهذه المشكلة هو تنفيذ عمليات التصدير والنسخ الاحتياطي ليلًا.
</p>

<p>
	رابعًا، فقد يكون هناك مشكلة في تناسق البيانات consistency إن كنت تملك خادوم MongoDB معرّض لضغط العمل باستمرار وبالتالي قد تتغير البيانات أثناء عملية التصدير، حيث لا يوجد حل بسيط لهذه المشكلة ولكن في نهاية المقال سنتحدث حول استنساخ البيانات replication.
</p>

<h2>
	استيراد المعلومات إلى قاعدة بيانات MongoDB
</h2>

<p>
	لنتعلّم كيفية استيراد المعلومات إلى قاعدة بيانات MongoDB، سنقوم باستخدام عيّنة قاعدة بيانات معروفة حول المطاعم. إنّ القاعدة بصيغة json ويمكن تحميلها باستخدام الأمر <span style="font-family:courier new,courier,monospace;">wget</span> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_11">
<span class="pln">$ wget https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json</span></pre>

<p>
	وحالما ينتهي التحميل ستحصل على ملف حجمه 12 ميغابايت يُدعى <span style="font-family:courier new,courier,monospace;">primer-dataset.json</span> في المجلّد الذي قمت بتنفيذ الأمر فيه. سنقوم باستيراد البيانات من هذا الملف إلى قاعدة بيانات جديدة سنسمّيها <span style="font-family:courier new,courier,monospace;">newdb</span> وضمن جدول سنسمّيه <span style="font-family:courier new,courier,monospace;">restaurants</span>. للقيام بعملية الاستيراد سنستخدم الأمر <span style="font-family:courier new,courier,monospace;">mongoimport</span> على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_13">
<span class="pln">$ sudo mongoimport --db newdb --collection restaurants --file primer-dataset.json</span></pre>

<p>
	ويُفترض أن تكون نتيجة تنفيذ الأمر السابق على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_17">
<span class="pln">2016-01-17T14:27:04.806-0500 	connected to: localhost
2016-01-17T14:27:07.315-0500 	imported 25359 documents</span></pre>

<p>
	وكما يظهر في الناتج السابق، فقد تم استيراد 25359 مستند، ولأننا لم نكن نملك قاعدة بيانات باسم <span style="font-family:courier new,courier,monospace;">newdb</span>، فقد قام محرّك MongoDB بإنشائها بشكل تلقائي، وللتأكّد من نجاح عملية الاستيراد سنقوم بالاتصال بقاعدة البيانات <span style="font-family:courier new,courier,monospace;">newdb</span> على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_19">
<span class="pln">$ sudo mongo newdb</span></pre>

<p>
	سنلاحظ عند تنفيذ الأمر بأن شكل مِحرف سطر الأوامر قد تغيّر، مما يشير إلى نجاح الاتصال بقاعدة البيانات، وللتحقق الآن من عدد المستندات التي تم استيرادها، سنقوم بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_21">
<span class="pln">&gt; db.restaurants.count()</span></pre>

<p>
	ويفترض أن تكون النتيجة 25359، وهو مطابق تمامًا لعدد المستندات المستوردة.
</p>

<p>
	وللتحقق بشكل أفضل من نجاح الاستيراد، سنقوم باختيار المستند الأول من مجموعة المطاعم بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_23">
<span class="pln">&gt; db.restaurants.findOne()</span></pre>

<p>
	وينبغي أن تكون النتيجة على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_4795_25">
<span class="pln">{
	"_id" : ObjectId("569beb098106480d3ed99926"),
	"address" : {
		"building" : "1007",
		"coord" : [
			-73.856077,
			40.848447
		],
		"street" : "Morris Park Ave",
		"zipcode" : "10462"
	},
	"borough" : "Bronx",
	"cuisine" : "Bakery",
	"grades" : [
		{
			"date" : ISODate("2014-03-03T00:00:00Z"),
			"grade" : "A",
			"score" : 2
		},
		...
	],
	"name" : "Morris Park Bake Shop",
	"restaurant_id" : "30075445"
}</span></pre>

<p>
	إنّ مثل هذا التحقق قد يظهر أيّ مشاكل في محتوى المستندات أو ترميزها أو ما شابه ذلك، فصيغة json تستخدم ترميز UTF-8 ويجب أن تكون البيانات المصدّرة والمستوردة بهذا الترميز. تذكّر هذا الأمر دومًا عند القيام بتحرير ملفات json بشكل يدوي، وفيما عدا ذلك فإنّ محرك MongoDB سيتولّى الأمر عنك بشكل تلقائي.
</p>

<p>
	أخيرًا، للخروج من سطر أوامر MongoDB نقوم بتنفيذ الأمر <span style="font-family:courier new,courier,monospace;">exit</span> على الشكل:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_27">
<span class="pln">&gt; exit</span></pre>

<p>
	وسيتم الخروج والعودة إلى سطر أوامر النظام كمستخدم عادي.
</p>

<h2>
	تصدير المعلومات من قاعدة بيانات MongoDB
</h2>

<p>
	كما ذكرنا سابقًا، فإنّه من الممكن الحصول على بيانات مقروءة ومفهومة عند القيام بتصدير المعلومات من قاعدة MongoDB، وتكون صيغة الملف المصدّر بشكل افتراضي هي json، ولكن من الممكن أيضًا الحصول على البيانات في ملف بصيغة (csv (comma separated value.
</p>

<p>
	نستخدم الأمر <span style="font-family:courier new,courier,monospace;">mongoexport</span> لتصدير البيانات من قاعدة MongoDB، ويسمح أمر التصدير باختيار قاعدة بيانات، مجموعة من المجموعات collection، حقل من الحقول، وحتّى استخدام استعلام من أجل التصدير.
</p>

<p>
	وكمثال بسيط على أمر التصدير <span style="font-family:courier new,courier,monospace;">mongoexport</span>، سنقوم بتصدير مجموعة المطاعم من قاعدة <span style="font-family:courier new,courier,monospace;">newdb</span> التي قمنا باستيرادها سابقًا، ويبدو الأمر على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_29">
<span class="pln">$ sudo mongoexport --db newdb -c restaurants --out newdbexport.json</span></pre>

<p>
	حيث قمنا في الأمر السابق باستخدام المُعامل <span style="font-family:courier new,courier,monospace;">db--</span> لتحديد القاعدة، والمُعامل<span style="font-family:courier new,courier,monospace;"> c-</span> لتحديد المجموعة، والمُعامل --out لتحديد اسم الملف الذي سيتم تصدير البيانات إليه، وستكون نتيجة تنفيذ الأمر السابق بشكل ناجح على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_31">
<span class="pln">2016-01-20T03:39:00.143-0500 	connected to: localhost
2016-01-20T03:39:03.145-0500 	exported 25359 records</span></pre>

<p>
	ويظهر الأمر السابق أنه قد تم تصدير 25359 مستند، وهو مماثل تمامًا لعدد المستندات التي قمنا باستيرادها سابقًا.
</p>

<p>
	قد نحتاج في بعض الأحيان إلى تصدير جزء من مجموعة، وبالأخذ بعين الاعتبار هيكل ومحتوى مستند المطاعم بصيغة json، سنقوم بتصدير معلومات جميع المطاعم التي تحقق الشرط الذي يقول بأنها موجودة في المنطقة الإدارية المسمّاة Bronx والتي تقدّم الطعام الصيني. للحصول على هذه المعلومات بشكل مباشر في حال كنّا متصلين بقاعدة MongoDB من خلال سطر أوامر MongoDB، فسنقوم بالاتصال بقاعدة البيانات مجددًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_33">
<span class="pln">$ sudo mongo newdb</span></pre>

<p>
	ومن ثم سنستخدم الاستعلام:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_35">
<span class="pln">&gt; db.restaurants.find( { borough: "Bronx", cuisine: "Chinese" } )</span></pre>

<p>
	وسيتم عرض النتيجة مباشرة، وللخروج من سطر أوامر MongoDB سننفّذ الأمر <span style="font-family:courier new,courier,monospace;">exit</span> كما ذكرنا سابقًا.
</p>

<p>
	أمّا لتصدير البيانات من سطر أوامر النظام دون أن نكون متصلين بقاعدة البيانات مسبقًا، فسنقوم بتمرير الاستعلام السابق كمُعامل لأمر <span style="font-family:courier new,courier,monospace;">mongoexport</span> باستخدام المُعامل <span style="font-family:courier new,courier,monospace;">q-</span> على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_39">
<span class="pln">$ sudo mongoexport --db newdb -c restaurants -q "{ borough: 'Bronx', cuisine: 'Chinese' }" --out Bronx_Chinese_retaurants.json</span></pre>

<p>
	لاحظ في الأمر السابق بأنّا قمنا باستخدام علامات الاقتباس الفرديّة ' داخل علامات الاقتباس الزوجيّة " لأنّ هذا شرط من شروط كتابة الاستعلام في سطر الأوامر، ولو احتجنا لاستخدام علامات اقتباس زوجيّة أو إشارة $ فسنحتاج لتخطي المحارف الخاصة باستخدام \ بإدراجها قبل المحرف الخاص في الاستعلام.
</p>

<p>
	إن تمت عملية التصدير بنجاح فينبغي أن تكون النتيجة على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4795_41">
<span class="pln">2016-01-20T04:16:28.381-0500 	connected to: localhost
2016-01-20T04:16:28.461-0500 	exported 323 records</span></pre>

<p>
	تُظهر النتيجة السابقة بأنّ هناك 323 سجل قد تم تصديره، ويمكن إيجادها ضمن ملف <span style="font-family:courier new,courier,monospace;">Bronx_Chinese_retaurants.json</span> الذي قمنا بتحديده.
</p>

<h2>
	الخلاصة
</h2>

<p>
	تعرفّنا في المقال على أساسيات استيراد وتصدير المعلومات من وإلى قاعدة بيانات MongoDB. إنّ عملية الاستنساخ replication مفيدة في حالة التوسعة، ولكنّها مهمة أيضًا للنواحي التي تحدثنا عنها، حيث تسمح باستمرارية تشغيل خدمات MongoDB دون انقطاع عبر خادوم MongoDB ثانوي بينما نقوم باستعادة نسخة احتياطية إلى الخادوم الرئيسي عند حدوث فشل. إن جزءًا من عملية الاستنساخ هو سجل العمليات (oplog)، الذي يقوم بتسجيل جميع العمليات التي تقوم بتغيير البيانات، ويمكن استخدام هذا السجل كما في MySQL، لاستعادة البيانات بعد أن تكون آخر عملية نسخ احتياطي قد بدأت. تذكّر بأن عمليات النسخ الاحتياطي تحصل في الليل عندما يكون نشاط قاعدة البيانات في حدّه الأدنى، وإن قررت استعادة نسخة احتياطية لقاعدة البيانات في الفترة المسائية (أي قبل أن تبدأ عملية النسخ الاحتياطي الليلية) فإنّك ستفقد بذلك جميع التعديلات التي تمت على القاعدة منذ آخر عملية نسخ احتياطي.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-import-and-export-a-mongodb-database-on-ubuntu-14-04" rel="external nofollow">How To Import and Export a MongoDB Database on Ubuntu 14.04</a> لصاحبه Anatoliy Dimitrov.
</p>
]]></description><guid isPermaLink="false">265</guid><pubDate>Fri, 10 Jun 2016 11:05:00 +0000</pubDate></item></channel></rss>
