MongoDB is a NoSQL document database for high volume data storage.
MongoDB uses collections and documents for its storage. Each document consists of key-value pairs using JSON-like syntax, similar to a dictionary or JavaScript object.
Likewise, as MongoDB is a NoSQL database, it uses its own query language, Mongo Query Language (MQL) which uses JSON for querying.
Getting Started ¶
Installation ¶
MongoDB can either be installed locally following the instructions here or you can create a remotely-hosted free 512 MB cluster here. Links to videos with instructions on setup are at the bottom.
This tutorial assumes that you have the MongoDB Shell from here. You can also download the graphical tool, MongoDB Compass, down below from the same link.
Components ¶
After installing MongoDB, you will notice there are multiple command line tools. The three most important of which are:
mongod
- The database server which is responsible for managing data and handling queriesmongos
- The sharding router, which is needed if data will be distributed across multiple machinesmongo
- The database shell (using JavaScript) through which we can configure our database
Usually we start the mongod
process and then use a separate terminal with
mongo
to access and modify our collections.
JSON & BSON ¶
While queries in MongoDB are made using a JSON-like* format, MongoDB stores its documents internally in the Binary JSON (BSON format). BSON is not human readable like JSON as it’s a binary encoding. However, this allows for end users to have access to more types than regular JSON, such as an integer or float type. Many other types, such as regular expressions, dates, or raw binary are supported too.
Here is the full list of all types that are supported.
- We refer JSON-like to mean JSON but with these extended types. For example, you can make queries directly with a regular expression or timestamp in MongoDB and you can receive data that has those types too.
1/////////////////////////////////////////////////////////
2/////////////////// Getting Started /////////////////////
3/////////////////////////////////////////////////////////
4
5// Start up the mongo database server
6// NOTE - You will need to do this in a separate terminal as the process will
7// take over the terminal. You may want to use the --fork option
8mongod // --fork
9
10// Connecting to a remote Mongo server
11// mongo "mongodb+srv://host.ip.address/admin" --username your-username
12
13// Mongoshell has a proper JavaScript interpreter built in
143 + 2 // 5
15
16// Show available databases
17// MongoDB comes with the following databases built-in: admin, config, local
18show dbs
19
20// Switch to a new database (pre-existing or about to exist)
21// NOTE: There is no "create" command for a database in MongoDB.
22// The database is created upon data being inserted into a collection
23use employees
24
25// Create a new collection
26// NOTE: Inserting a document will implicitly create a collection anyways,
27// so this is not required
28db.createCollection('engineers')
29db.createCollection('doctors')
30
31// See what collections exist under employees
32show collections
33
34/////////////////////////////////////////////////////////
35// Basic Create/Read/Update/Delete (CRUD) Operations: ///
36/////////////////////////////////////////////////////////
37
38/////////////// Insert (Create) /////////////////////////
39
40// Insert one employee into the database
41// Each insertion returns acknowledged true or false
42// Every document has a unique _id value assigned to it automatically
43db.engineers.insertOne({ name: "Jane Doe", age: 21, gender: 'Female' })
44
45// Insert a list of employees into the `engineers` collection
46// Can insert as an array of objects
47db.engineers.insert([
48 { name: "Foo Bar", age: 25, gender: 'Male' },
49 { name: "Baz Qux", age: 27, gender: 'Other' },
50])
51
52// MongoDB does not enforce a schema or structure for objects
53// Insert an empty object into the `engineers` collection
54db.engineers.insertOne({})
55
56// Fields are optional and do not have to match rest of documents
57db.engineers.insertOne({ name: "Your Name", gender: "Male" })
58
59// Types can vary and are preserved on insertion
60// This can require additional validation in some languages to prevent problems
61db.engineers.insert({ name: ['Foo', 'Bar'], age: 3.14, gender: true })
62
63// Objects or arrays can be nested inside a document
64db.engineers.insertOne({
65 name: "Your Name",
66 gender: "Female",
67 skilledIn: [
68 "MongoDB",
69 "NoSQL",
70 ],
71 "date-of-birth": {
72 "date": 1993-07-20T09:44:18.674Z,
73 "age": 26
74 },
75})
76
77// We can override the _id field
78// Works fine
79db.engineers.insertOne({
80 _id: 1,
81 name: "An Engineer",
82 age: 25,
83 gender: "Female",
84})
85
86// Be careful, as _id must ALWAYS be unique for the collection otherwise
87// the insertion will fail
88// Fails with a WriteError indicating _id is a duplicate value
89db.engineers.insertOne({
90 _id: 1,
91 name: "Another Engineer",
92 age: 25,
93 gender: "Male",
94})
95
96// Works fine as this is a different collection
97db.doctors.insertOne({
98 _id: 1,
99 name: "Some Doctor",
100 age: 26,
101 gender: "Other",
102})
103
104/////////////////// Find (Read) ////////////////////////
105// Queries are in the form of db.collectionName.find(<filter>)
106// Where <filter> is an object
107
108// Show everything in our database so far, limited to a
109// maximum of 20 documents at a time
110// Press i to iterate this cursor to the next 20 documents
111db.engineers.find({})
112
113// We can pretty print the result of any find() query
114db.engineers.find({}).pretty()
115
116// MongoDB queries take in a JS object and search for documents with matching
117// key-value pairs
118// Returns the first document matching query
119// NOTE: Order of insertion is not preserved in the database, output can vary
120db.engineers.findOne({ name: 'Foo Bar' })
121
122// Returns all documents with the matching key-value properties as a cursor
123// (which can be converted to an array)
124db.engineers.find({ age: 25 })
125
126// Type matters when it comes to queries
127// Returns nothing as all ages above are integer type
128db.engineers.find({ age: '25' })
129
130// find() supports nested objects and arrays just like create()
131db.engineers.find({
132 name: "Your Name",
133 gender: "Female",
134 skilledIn: [
135 "MongoDB",
136 "NoSQL",
137 ],
138 "date-of-birth": {
139 "date": 1993-07-20T09:44:18.674Z,
140 "age": 26
141 },
142})
143
144///////////////////////// Update ////////////////////////
145// Queries are in the form of db.collectionName.update(<filter>, <update>)
146// NOTE: <update> will always use the $set operator.
147// Several operators are covered later on in the tutorial.
148
149// We can update a single object
150db.engineers.updateOne({ name: 'Foo Bar' }, { $set: { name: 'John Doe', age: 100 }})
151
152// Or update many objects at the same time
153db.engineers.update({ age: 25 }, { $set: { age: 26 }})
154
155// We can use { upsert: true } if we would like it to insert if the document doesn't already exist,
156// or to update if it does
157// Returns matched, upserted, modified count
158db.engineers.update({ name: 'Foo Baz' },
159 { $set:
160 {
161 age: 26,
162 gender: 'Other'
163 }
164 },
165 { upsert: true }
166)
167
168/////////////////////// Delete /////////////////////////
169// Queries are in the form of db.collectionName.delete(<filter>)
170
171// Delete first document matching query, always returns deletedCount
172db.engineers.deleteOne({ name: 'Foo Baz' })
173
174// Delete many documents at once
175db.engineers.deleteMany({ gender: 'Male' })
176
177// NOTE: There are two methods db.collection.removeOne(<filter>) and
178// db.collection.removeMany(<filter>) that also delete objects but have a
179// slightly different return value.
180// They are not included here as they have been deprecated in the NodeJS driver.
181
182/////////////////////////////////////////////////////////
183//////////////////// Operators //////////////////////////
184/////////////////////////////////////////////////////////
185
186// Operators in MongoDB have a $ prefix. For this tutorial, we are only looking
187// at comparison and logical operators, but there are many other types of
188// operators
189
190//////////////// Comparison Operators ///////////////////
191
192// Find all greater than or greater than equal to some condition
193db.engineers.find({ age: { $gt: 25 }})
194db.engineers.find({ age: { $gte: 25 }})
195
196// Find all less than or less than equal to some condition
197db.engineers.find({ age: { $lt: 25 }})
198db.engineers.find({ age: { $lte: 25 }})
199
200// Find all equal or not equal to
201// Note: the $eq operator is added implicitly in most queries
202db.engineers.find({ age: { $eq: 25 }})
203db.engineers.find({ age: { $ne: 25 }})
204
205// Find all that match any element in the array, or not in the array
206db.engineers.find({ age: { $in: [ 20, 23, 24, 25 ]}})
207db.engineers.find({ age: { $nin: [ 20, 23, 24, 25 ]}})
208
209//////////////// Logical Operators ///////////////////
210
211// Join two query clauses together
212// NOTE: MongoDB does this implicitly for most queries
213db.engineers.find({ $and: [
214 gender: 'Female',
215 age: {
216 $gte: 18
217 }
218]})
219
220// Match either query condition
221db.engineers.find({ $or: [
222 gender: 'Female',
223 age: {
224 $gte: 18
225 }
226]})
227
228// Negates the query
229db.engineers.find({ $not: {
230 gender: 'Female'
231}})
232
233// Must match none of the query conditions
234db.engineers.find({ $nor [
235 gender: 'Female',
236 age: {
237 $gte: 18
238 }
239]})
240
241/////////////////////////////////////////////////////////
242//////////////// Database Operations: ///////////////////
243/////////////////////////////////////////////////////////
244
245// Delete (drop) the employees database
246// THIS WILL DELETE ALL DOCUMENTS IN THE DATABASE!
247db.dropDatabase()
248
249// Create a new database with some data
250use example
251db.test.insertOne({ name: "Testing data, please ignore!", type: "Test" })
252
253// Quit Mongo shell
254exit
255
256// Import/export database as BSON:
257
258// Mongodump to export data as BSON for all databases
259// Exported data is found in under "MongoDB Database Tools/bin/dump"
260// NOTE: If the command is not found, navigate to "MongoDB Database Tools/bin"
261// and use the executable from there mongodump
262
263// Mongorestore to restore data from BSON
264mongorestore dump
265
266// Import/export database as JSON:
267// Mongoexport to export data as JSON for all databases
268mongoexport --collection=example
269
270// Mongoimport to export data as JSON for all databases
271mongoimport --collection=example
Further Reading ¶
Setup Videos ¶
Input Validation ¶
From the examples above, if input validation or structure is a concern, I would take a look at the following ORMs:
- Mongoose (Node.js) - Input validation through schemas that support types, required values, minimum and maximum values.
- MongoEngine (Python) - Similar to Mongoose, but I found it somewhat limited in my experience
- MongoKit (Python) - Another great alternative to MongoEngine that I find easier to use than MongoEngine
For statically strongly typed languages (e.g. Java, C++, Rust), input validation usually doesn’t require a library as they define types and structure at compile time.
Resources ¶
If you have the time to spare, I would strongly recommend the courses on MongoDB University. They’re by MongoDB themselves and go into much more detail while still being concise. They’re a mix of videos and quiz questions and this was how I gained my knowledge of MongoDB.
I would recommend the following video series for learning MongoDB:
Language-specific ones that I used before:
- Build A REST API With Node.js, Express, & MongoDB - Web Dev Simplified
- MongoDB with Python Crash Course - Tutorial for Beginners - FreeCodeCamp
- How to Use MongoDB with Java - Random Coder
- An Introduction to Using MongoDB with Rust - MongoDB
Most of the information above was cross-referenced with the MongoDB docs. Here are the docs for each section:
- MongoDB Types - List of all types that MongoDB supports natively
- MongoDB Operators - List of operators MongoDB supports natively
- MongoDB CRUD - Commands for create, read, update, delete
If you’ve been enjoying MongoDB so far and want to explore intermediate features, I would look at aggregation, indexing, and sharding.
- Aggregation - useful for creating advanced queries to be executed by the database
- Indexing allows for caching, which allows for much faster execution of queries
- Sharding allows for horizontal data scaling and distribution between multiple machines.