MongoDB Overview
A database is simply a storage mechanism for information. In the same way a warehouse stores physical inventory in rows, on shelves, in boxes, etc., a database stores data in it’s own organized way. The two types of database structures are relational (SQL) and non-relational (NoSQL).
Relational vs. Non-Relational Databases
Relational databases are an older, more time-tested type of database that has been around for over 40 years. Virtually all relational databases use SQL (Structured Query Language) as the language for querying and maintaining the database, hence the “SQL” in the name of many of the different brands of databases available: PostgreSQL, MySQL, SQLite, etc.
A relational database is comprised of a number of tables that relate to each other. Each table represents a different type of entity in the database, and different entity types will relate to each other through ID numbers we call Primary Keys and Foreign Keys. The simplest way to think about these tables is to think of a spreadsheet table system. A database table is similar to a spreadsheet where each row represents an individual record (or entry) in the database, and each column represents a different property of each entry.
For example, if your database table represented a collection of people for an address book, your columns might be "first name", "last name", "phone number", "address", "email address", etc. and your rows would be that information for each individual person in your address book.
The thing that makes a relational database relational is that you use unique IDs (or keys) for each entry on any given table to connect entries in the table together. Since we're going to be focusing on Non-relational databases, we won't dive too deep into this right now, but if you want to check out a great resource for understanding relational databases, check out this YouTube playlist on database design.
A non-relational database is, simply put, a collection of "documents" where all of the data from the application is stored. It can be very helpful to think of these "collections" like large JSON objects full of nested arrays and objects. These collections are analogous to relational database tables in that each collection usually refers to a single type of data (the "people" from your address book). The main difference however, is that it is loosely structured. In a relational database, you must tell the database exactly what data each table is going to hold, and it will enforce that data structure on every piece of data. This makes changing the structure of your data difficult, especially if there is already data existing in the database.
Two main benefits of non-relational databases are 1) that they tend to scale better than relational databases, so as your database grows in size it continues to perform well, and 2) that they are more flexible than relational databases. If you need to change the structure of your database as your business grows, it is a lot easier to do so with a NoSQL database.
This is mostly technical talk so far, but with practice it'll make more sense. One important thing to understand about NoSQL databases as it relates to your progress as a student is that it makes transferring data between our server and our client drop-dead simple. Since it's being stored essentially as a JSON object, all it has to do is send the data directly from the database to our AngularJS frontend, and Angular already knows exactly how to translate it for use.
Installing on Mac
Check out the instructions on Mac OSX installation.
Installing on Linux
Check out instructions on Linux installation
Controlling MongoDB in the command-line
To enter the MongoDB shell, where you can manually view, delete, update, etc. data inside your database, simply type mongo
in a terminal window. This opens the mongo shell.
Create a new db:
use your-database-name
This will create a new database called your-database-name
if it doesn't exist, OR it will switch to that database if it does already exist. It's a pretty handy shortcut.
Check which db you're using:
db
Entering db
will display which database you're currently use
ing.
Delete a database:
While inside the database you want to delete (after entering use your-database-name
), enter:
db.dropDatabase()
Be SUPER careful with this, because it will delete all your data without confirming, and you can't get it back.
Insert a JSON document as initial data in Mongo:
db.<collectionName>.insert({ key: value, key: value, etc. })
# Where key: value represents real key: value pairs of information you want to insert into the document.
# If this <collectionName> doesn't yet exist, MongoDB will create it before adding any data.
# example:
db.contact.insert({ firstName: "Jerry", lastName: "Gergich", email: "lennyGengurch@pawneein.gov" })
If you want to insert a bunch at once, you can insert an array of people:
db.contact.insert([{ firstName: "Jerry", lastName: "Gergich", email: "lennyGengurch@pawneein.gov" }, { firstName: "Ann", lastName: "Perkins", email: "a.cakes.perkins@pawneein.gov" }, { etc. }])
Show all existing collections:
show collections
# prints "people" and "system.indexes" to the console.
Find all data (documents) inside one collection:
db.<collectionName>.find()
# example:
db.people.find() # prints a minified version of all your data. Use the .pretty() command to make it more readable:
db.people.find().pretty()
objectIds
Every time Mongo inserts a new document into a collection, it assigns a unique ID to that document. This allows us to reference the exact item we want if we were to ever, for example, remove that item from the database. This way, if you ever had two contacts named "Sam Smith" in your address book, you could remove the exact one you want by referencing it's unique ID.
Remove a document from a collection
db.<collectionName>.remove( <selectionCriteria> )
# The <selectionCriteria> is a way to search for the specific item you want removed from <collectionName>. For example:
db.people.remove( {firstName: "Bob"} ) # Removes any people from your address book with the firstName of "Bob". If you want to get more specific, then using the ObjectId attribute that MongoDB assigned your person is a more sure way of deleting just one item:
db.people.remove( {"_id": ObjectId("55asdf5sdf68sdfsd6g8")} )
Update a document
For changing some information on one document
db.<collectionName>.update(<selectionCriteria>, <newData>)
# example:
db.people.update( { "_id": ObjectId("55asdf5sdf68sdfsd6g8") }, { "firstName": "Lenny", "lastName": "Gengurch" } )
Remove an entire collection:
db.<collectionName>.drop()
Be VERY careful with this command, as it will lose you all the information from that collection.
Search criteria queries
As shown before, you can search through a collection and return all documents that match a certain criteria. If you want to get everyone with the same last name in your address book:
db.people.find( {"lastName": "Smith"} ) # Returns all documents in the "people" collection with a "lastName" property with the value of "Smith".
You can get as specific as you want by adding additional search criteria to your object, separated by a comma:
db.people.find( {"lastName": "Smith", "age": 25} ) # Finds all people with the last name of "Smith" AND who are 25 years old.
MongoDB's built-in search tools
When you're simply searching if a key equals a certain value, you don't need anything other than to specify the search criteria as shown above. However, if you want MongoDB to do some logic for you before it returns any results (such as "find all people who are older than 17"), you'll need to use some of MongoDB's built-in search tools. These built-in logical tools begin with a $
and are used as properties of their own object:
$gt, $lt, $gte, $lte, $ne:
For finding greater than, less than, greater than or equal to, less than or equal to, or not equal to.
db.people.find( { "age" : { $gt: 17 } } ) # Finds all people with an "age" property that is greater than 17.
$or:
Allows you to use the logical or
operator on queries:
# Find all people with EITHER the last name of "Smith" OR last name of "Johnson". This query has been spaced out so it's easier to read with all the braces/brackets/parentheses, etc.
db.people.find({
$or: [
{"lastName": "Smith"},
{"lastName": "Johnson"}
]
})
The above $or
doesn't need to be for the same property either, so we could search for all people with the last name of "Smith" OR all people with an age of 25.
Returning only what you need from a .find()
If you don't need ALL the information about the documents that match your query, you can specify which fields you want the search to return in the second parameter of the .find()
method by either explicitly turning some properties on (setting that property to 1
) or turning them off (setting that property to 0
):
# Returns the first names of all people with the last name of Smith, and DOESN'T return the _id property (which is would otherwise automatically do by default).
db.people.find(
{"lastName": "Smith"},
{"firstName": 1, "_id": 0} # MongoDB automatically includes the "_id" so if you don't want it included, you need to explicitly turn it off.
);
Conclusion
There are a TON more kinds of queries you can make straight from the mongo shell to help you manipulate, speed up, group, etc. your data. However, for our purposes this is only meant to be a basic introduction to MongoDB in general and some commands you can run to directly manipulate your data so that you have a chance to become more familiar with MongoDB in general.
Since you're not going to be running commands directly into the MongoDB shell to manipulate the data (you're likely going to be using a package like Mongoose that lets you abstract these commands so you can let your server run them in JavaScript instead), it's not super important that you memorize all these commands. Check out the post on Intro to Mongoose for a better understanding of how to programmatically manipulate data in your Mongo database directly from your Express server's JavaScript code.