all repos — gemini-redirect @ bb1c3c6a132b8617271fc574b1805b283f943179

blog/ribw/mongodb-basic-operations-and-architecture/index.html (view raw)

  1<!DOCTYPE html>
  2<html>
  3<head>
  4<meta charset="utf-8" />
  5<meta name="viewport" content="width=device-width, initial-scale=1" />
  6<title>MongoDB: Basic Operations and Architecture</title>
  7<link rel="stylesheet" href="../css/style.css">
  8</head>
  9<body>
 10<main>
 11<p>This is the second post in the MongoDB series, where we will take a look at the <a href="https://stackify.com/what-are-crud-operations/">CRUD operations</a> they support, the data model and architecture used.</p>
 12<div class="date-created-modified">Created 2020-03-05<br>
 13Modified 2020-04-08</div>
 14<p>Other posts in this series:</p>
 15<ul>
 16<li><a href="/blog/ribw/mongodb-an-introduction/">MongoDB: an Introduction</a></li>
 17<li><a href="/blog/ribw/mongodb-basic-operations-and-architecture/">MongoDB: Basic Operations and Architecture</a> (this post)</li>
 18<li><a href="/blog/ribw/developing-a-python-application-for-mongodb/">Developing a Python application for MongoDB</a></li>
 19</ul>
 20<p>This post is co-authored wih Classmate, and in it we will take an explorative approach using the <code>mongo</code> command line shell to execute commands against the database. It even has TAB auto-completion, which is awesome!</p>
 21<hr />
 22<p>Before creating any documents, we first need to create somewhere for the documents to be in. And before we create anything, the database has to be running, so let’s do that first. If we don’t have a service installed, we can run the <code>mongod</code> command ourselves in some local folder to make things easier:</p>
 23<pre><code>$ mkdir -p mongo-database
 24$ mongod --dbpath mongo-database
 25</code></pre>
 26<p>Just like that, we will have Mongo running. Now, let’s connect to it using the <code>mongo</code> command in another terminal (don’t close the terminal where the server is running, we need it!). By default, it connects to localhost, which is just what we need.</p>
 27<pre><code>$ mongo
 28</code></pre>
 29<h2 class="title" id="create"><a class="anchor" href="#create">¶</a>Create</h2>
 30<h3 id="create_a_database"><a class="anchor" href="#create_a_database">¶</a>Create a database</h3>
 31<p>Let’s list the databases:</p>
 32<pre><code>&gt; show databases
 33admin   0.000GB
 34config  0.000GB
 35local   0.000GB
 36</code></pre>
 37<p>Oh, how interesting! There’s already some databases, even though we just created the directory where Mongo will store everything. However, they seem empty, which make sense.</p>
 38<p>Creating a new database is done by <code>use</code>-ing a name that doesn’t exist. Let’s call our new database «helloworld».</p>
 39<pre><code>&gt; use helloworld
 40switched to db helloworld
 41</code></pre>
 42<p>Good! Now the «local variable» called <code>db</code> points to our <code>helloworld</code> database.</p>
 43<pre><code>&gt; db
 44helloworld
 45</code></pre>
 46<p>What happens if we print the databases again? Surely our new database will show up now…</p>
 47<pre><code>&gt; show databases
 48admin   0.000GB
 49config  0.000GB
 50local   0.000GB
 51</code></pre>
 52<p>…maybe not! It seems Mongo won’t create the database until we create some collections and documents in it. Databases contain collections, and inside collections (which you can think of as tables) we can insert new documents (which you can think of as rows). Like in many programming languages, the dot operator is used to access these «members».</p>
 53<h3 id="create_a_document"><a class="anchor" href="#create_a_document">¶</a>Create a document</h3>
 54<p>Let’s add a new greeting into the <code>greetings</code> collection:</p>
 55<pre><code>&gt; db.greetings.insert({message: &quot;¡Bienvenido!&quot;, lang: &quot;es&quot;})
 56WriteResult({ &quot;nInserted&quot; : 1 })
 57
 58&gt; show collections
 59greetings
 60
 61&gt; show databases
 62admin       0.000GB
 63config      0.000GB
 64helloworld  0.000GB
 65local       0.000GB
 66</code></pre>
 67<p>That looks promising! We can also see our new <code>helloworld</code> database also shows up. The Mongo shell actually works on JavaScript-like code, which is why we can use a variant of JSON (BSON) to insert documents (note the lack of quotes around the keys, convenient!).</p>
 68<p>The <a href="https://docs.mongodb.com/manual/reference/method/db.collection.insert/index.html"><code>insert</code></a> method actually supports a list of documents, and by default Mongo will assign a unique identifier to each. If we don’t want that though, all we have to do is add the <code>_id</code> key to our documents.</p>
 69<pre><code>&gt; db.greetings.insert([
 70... {message: &quot;Welcome!&quot;, lang: &quot;en&quot;},
 71... {message: &quot;Bonjour!&quot;, lang: &quot;fr&quot;},
 72... ])
 73BulkWriteResult({
 74    &quot;writeErrors&quot; : [ ],
 75    &quot;writeConcernErrors&quot; : [ ],
 76    &quot;nInserted&quot; : 2,
 77    &quot;nUpserted&quot; : 0,
 78    &quot;nMatched&quot; : 0,
 79    &quot;nModified&quot; : 0,
 80    &quot;nRemoved&quot; : 0,
 81    &quot;upserted&quot; : [ ]
 82})
 83</code></pre>
 84<h3 id="create_a_collection"><a class="anchor" href="#create_a_collection">¶</a>Create a collection</h3>
 85<p>In this example, we created the collection <code>greetings</code> implicitly, but behind the scenes Mongo made a call to <a href="https://docs.mongodb.com/manual/reference/method/db.createCollection/"><code>createCollection</code></a>. Let’s do just that:</p>
 86<pre><code>&gt; db.createCollection(&quot;goodbyes&quot;)
 87{ &quot;ok&quot; : 1 }
 88
 89&gt; show collections
 90goodbyes
 91greetings
 92</code></pre>
 93<p>The method actually has a default parameter to configure other options, like the maximum size of the collection or maximum amount of documents in it, validation-related options, and so on. These are all described in more details in the documentation.</p>
 94<h2 id="read"><a class="anchor" href="#read">¶</a>Read</h2>
 95<p>To read the contents of a document, we have to <a href="https://docs.mongodb.com/manual/reference/method/db.collection.find/index.html"><code>find</code></a> it.</p>
 96<pre><code>&gt; db.greetings.find()
 97{ &quot;_id&quot; : ObjectId(&quot;5e74829a0659f802b15f18dd&quot;), &quot;message&quot; : &quot;¡Bienvenido!&quot;, &quot;lang&quot; : &quot;es&quot; }
 98{ &quot;_id&quot; : ObjectId(&quot;5e7487b90659f802b15f18de&quot;), &quot;message&quot; : &quot;Welcome!&quot;, &quot;lang&quot; : &quot;en&quot; }
 99{ &quot;_id&quot; : ObjectId(&quot;5e7487b90659f802b15f18df&quot;), &quot;message&quot; : &quot;Bonjour!&quot;, &quot;lang&quot; : &quot;fr&quot; }
100</code></pre>
101<p>That’s a bit unreadable for my taste, can we make it more <a href="https://docs.mongodb.com/manual/reference/method/cursor.pretty/index.html"><code>pretty</code></a>?</p>
102<pre><code>&gt; db.greetings.find().pretty()
103{
104    &quot;_id&quot; : ObjectId(&quot;5e74829a0659f802b15f18dd&quot;),
105    &quot;message&quot; : &quot;¡Bienvenido!&quot;,
106    &quot;lang&quot; : &quot;es&quot;
107}
108{
109    &quot;_id&quot; : ObjectId(&quot;5e7487b90659f802b15f18de&quot;),
110    &quot;message&quot; : &quot;Welcome!&quot;,
111    &quot;lang&quot; : &quot;en&quot;
112}
113{
114    &quot;_id&quot; : ObjectId(&quot;5e7487b90659f802b15f18df&quot;),
115    &quot;message&quot; : &quot;Bonjour!&quot;,
116    &quot;lang&quot; : &quot;fr&quot;
117}
118</code></pre>
119<p>Gorgeous! We can clearly see Mongo created an identifier for us automatically. The queries are also JSON, and support a bunch of operators (prefixed by <code>$</code>), known as <a href="https://docs.mongodb.com/manual/reference/operator/query/">Query Selectors</a>. Here’s a few:</p>
120<table>
121 <thead>
122  <tr>
123   <th>
124    Operation
125   </th>
126   <th>
127    Syntax
128   </th>
129   <th>
130    RDBMS equivalent
131   </th>
132  </tr>
133 </thead>
134 <tbody>
135  <tr>
136   <td>
137    Equals
138   </td>
139   <td>
140    <code>
141     {key: {$eq: value}}
142    </code>
143    <br/>
144    Shorthand:
145    <code>
146     {key: value}
147    </code>
148   </td>
149   <td>
150    <code>
151     where key = value
152    </code>
153   </td>
154  </tr>
155  <tr>
156   <td>
157    Less Than
158   </td>
159   <td>
160    <code>
161     {key: {$lte: value}}
162    </code>
163   </td>
164   <td>
165    <code>
166     where key &lt; value
167    </code>
168   </td>
169  </tr>
170  <tr>
171   <td>
172    Less Than or Equal
173   </td>
174   <td>
175    <code>
176     {key: {$lt: value}}
177    </code>
178   </td>
179   <td>
180    <code>
181     where key &lt;= value
182    </code>
183   </td>
184  </tr>
185  <tr>
186   <td>
187    Greater Than
188   </td>
189   <td>
190    <code>
191     {key: {$gt: value}}
192    </code>
193   </td>
194   <td>
195    <code>
196     where key &gt; value
197    </code>
198   </td>
199  </tr>
200  <tr>
201   <td>
202    Greater Than or Equal
203   </td>
204   <td>
205    <code>
206     {key: {$gte: value}}
207    </code>
208   </td>
209   <td>
210    <code>
211     where key &gt;= value
212    </code>
213   </td>
214  </tr>
215  <tr>
216   <td>
217    Not Equal
218   </td>
219   <td>
220    <code>
221     {key: {$ne: value}}
222    </code>
223   </td>
224   <td>
225    <code>
226     where key != value
227    </code>
228   </td>
229  </tr>
230  <tr>
231   <td>
232    And
233   </td>
234   <td>
235    <code>
236     {$and: [{k1: v1}, {k2: v2}]}
237    </code>
238   </td>
239   <td>
240    <code>
241     where k1 = v1 and k2 = v2
242    </code>
243   </td>
244  </tr>
245  <tr>
246   <td>
247    Or
248   </td>
249   <td>
250    <code>
251     {$or: [{k1: v1}, {k2: v2}]}
252    </code>
253   </td>
254   <td>
255    <code>
256     where k1 = v1 or k2 = v2
257    </code>
258   </td>
259  </tr>
260 </tbody>
261</table>
262<p>The operations all do what you would expect them to do, and their names are really intuitive. Aggregating operations with <code>$and</code> or <code>$or</code> can be done anywhere in the query, nested any level deep.</p>
263<h2 id="update"><a class="anchor" href="#update">¶</a>Update</h2>
264<p>Updating a document can be done by using <a href="https://docs.mongodb.com/manual/reference/method/db.collection.save/index.html"><code>save</code></a> on an already-existing document (that is, the document we want to save has <code>_id</code> and it’s in the collection already). If the document is not in the collection yet, this method will create it.</p>
265<pre><code>&gt; db.greetings.save({_id: ObjectId(&quot;5e74829a0659f802b15f18dd&quot;), message: &quot;¡Bienvenido, humano!&quot;, &quot;lang&quot; : &quot;es&quot;})
266WriteResult({ &quot;nMatched&quot; : 1, &quot;nUpserted&quot; : 0, &quot;nModified&quot; : 1 })
267
268&gt; db.greetings.find({lang: &quot;es&quot;})
269{ &quot;_id&quot; : ObjectId(&quot;5e74829a0659f802b15f18dd&quot;), &quot;message&quot; : &quot;¡Bienvenido, humano!&quot;, &quot;lang&quot; : &quot;es&quot; }
270</code></pre>
271<p>Alternatively, the <a href="https://docs.mongodb.com/manual/reference/method/db.collection.update/index.html"><code>update</code></a> method takes a query and new value.</p>
272<pre><code>&gt; db.greetings.update({lang: &quot;en&quot;}, {$set: {message: &quot;Welcome, human!&quot;}})
273WriteResult({ &quot;nMatched&quot; : 1, &quot;nUpserted&quot; : 0, &quot;nModified&quot; : 1 })
274
275&gt; db.greetings.find({lang: &quot;en&quot;})
276{ &quot;_id&quot; : ObjectId(&quot;5e7487b90659f802b15f18de&quot;), &quot;message&quot; : &quot;Welcome, human!&quot;, &quot;lang&quot; : &quot;en&quot; }
277</code></pre>
278<h2 id="indexing"><a class="anchor" href="#indexing">¶</a>Indexing</h2>
279<p>Creating an index is done with <a href="https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/index.html"><code>createIndex</code></a>:</p>
280<pre><code>&gt; db.greetings.createIndex({lang: +1})
281{
282    &quot;createdCollectionAutomatically&quot; : false,
283    &quot;numIndexesBefore&quot; : 1,
284    &quot;numIndexesAfter&quot; : 2,
285    &quot;ok&quot; : 1
286}
287</code></pre>
288<p>Here, we create an ascending index on the lang key. Descending order is done with <code>-1</code>. Now a query for <code>lang</code> in our three documents will be fast… well maybe iteration over three documents was faster than an index.</p>
289<h2 id="delete"><a class="anchor" href="#delete">¶</a>Delete</h2>
290<h3 id="delete_a_document"><a class="anchor" href="#delete_a_document">¶</a>Delete a document</h3>
291<p>I have to confess, I can’t talk French. I learnt it long ago and it’s long forgotten, so let’s remove the translation I copied online from our greetings with <a href="https://docs.mongodb.com/manual/reference/method/db.collection.remove/index.html"><code>remove</code></a>.</p>
292<pre><code>&gt; db.greetings.remove({lang: &quot;fr&quot;})
293WriteResult({ &quot;nRemoved&quot; : 1 })
294</code></pre>
295<h3 id="delete_a_collection"><a class="anchor" href="#delete_a_collection">¶</a>Delete a collection</h3>
296<p>We never really used the <code>goodbyes</code> collection. Can we get rid of that?</p>
297<pre><code>&gt; db.goodbyes.drop()
298true
299</code></pre>
300<p>Yes, it is <code>true</code> that we can <a href="https://docs.mongodb.com/manual/reference/method/db.collection.drop/index.html"><code>drop</code></a> it.</p>
301<h3 id="delete_a_database"><a class="anchor" href="#delete_a_database">¶</a>Delete a database</h3>
302<p>Now, I will be honest, I don’t really like our <code>greetings</code> database either. It stinks. Let’s get rid of it as well:</p>
303<pre><code>&gt; db.dropDatabase()
304{ &quot;dropped&quot; : &quot;helloworld&quot;, &quot;ok&quot; : 1 }
305</code></pre>
306<p>Yeah, take that! The <a href="https://docs.mongodb.com/manual/reference/method/db.dropDatabase/"><code>dropDatabase</code></a> can be used to drop databases.</p>
307<h2 id="references"><a class="anchor" href="#references">¶</a>References</h2>
308<p>The examples in this post are all fictional, and the methods that could be used where taken from Classmate’s post, and of course <a href="https://docs.mongodb.com/manual/reference/method/">Mongo’s documentation</a>.</p>
309</main>
310</body>
311</html>
312