---
# System prepended metadata

title: MongoDB | Shell & CRUD operations
tags: [ironhack, ' lecture']

---

---
tags: ironhack, lecture, 
---

<style>
.markdown-body img[src$=".png"] {background-color:transparent;}

.alert-info.lecture,
.alert-success.lecture,
.alert-warning.lecture,
.alert-danger.lecture {
  box-shadow:0 0 0 .5em rgba(64, 96, 85, 0.4); margin-top:20px;margin-bottom:20px;
  position:relative;
  ddisplay:none;
  
}

.alert-info.lecture:before,
.alert-success.lecture:before,
.alert-warning.lecture:before,
.alert-danger.lecture:before {
  content:"👨‍🏫\A"; white-space:pre-line;
  display:block;margin-bottom:.5em;
  /*position:absolute; right:0; top:0;
  margin:3px;margin-right:7px;*/
}

b {
  --color:yellow;
  font-weight:500;
  background:var(--color); box-shadow:0 0 0 .35em var(--color),0 0 0 .35em;
}

.skip {
  opacity:.4;
}
</style>

![Ironhack Logo](https://i.imgur.com/1QgrNNw.png)

# MongoDB | Shell & CRUD operations

## Learning goals

After this lesson, you will be able to:

- Use the MongoShell to Create, Read, Update and Delete Documents

## Intro 

![](https://i.imgur.com/NzalR30.png)

:::info lecture
CRUD
:::

When working with any Database, there are a few operations that we will always need to use. These operations are so popular that we have an acronym for it:  [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) stands for `create`, `read`, `update` and `delete`:

![](https://i.imgur.com/CRowB2i.png)

These are the basic operations to persist data in our Database and with them, we can do anything we want. Ready? 

## Quick Recap

### Database commands

We can launch the mongoShell by simply typing `mongo` in our terminal. Remember that each mongo server can hold many **databases**.

| Database Command | Explanation
|------------------|--------------
| `show dbs`       | List all the databases inside our mongo server
| `use <dbName>`   | This will switch to the database `dbName` or create it if it doesn't exist
| `db`             | Show the name of the current database

### Collection commands

A Database is composed of different **collections**. This lesson will be focused on how to create, read, update and delete documents inside a collection. But first of all, let's take a look at a couple of useful collection commands:

| Collection Command | Explanation
|--------------------|--------------
|`show collections ` | List all the collections inside the current database

### JSON Documents

Each Collection is composed of different **documents**. A document is nothing more than a JSON object, with different **keys** and its associated values. We can identify a document by its `_id` property that mongo generates automatically for us.

**Example:**
```javascript
{
  "_id" : ObjectId("58401d8b71caea72370262c1"), 
  "name" : "John Doe", 
  "age" : 25,
  "address": {
    "country": "Japan",
    "address": "#901, 74-1 Yamashita-cho, Naka-ku"
  }
}
```

## Create | Inserting Documents

Create commands allow us to insert new documents into a collection. If the collection doesn't exist, the operation will create it.

| Insert Command | Summary
|----------------|--------------------
| db.collection.insertOne(doc)     | Adds a document to the collection
| db.collection.insertMany([docs]) | Adds one or more documents to the collection


### insertOne()

The [db.collection.insertOne](https://docs.mongodb.com/v3.2/reference/method/db.collection.insertOne/) command inserts a single document into the collection.


**Example:**
```javascript
> db.enemies.insertOne({ 
    "name": "Blinky", 
    "color": "Red"
})

// The command returns an object with the following structure
//
// {
// 	"acknowledged" : true,
// 	"insertedId" : ObjectId("583c63f96fa7d619e2c574e6")
// }
```

:::info
**Notes**
- Since we don't have a collection called `enemies`, it will be created automatically
- As you can see, the document didn't have an `id`, so MongoDB created one for us
:::


**Another Example**
```javascript
> db.enemies.insertOne({
    "_id": 10,
    "name": "Pinky", 
    "color": "Pink",
    "status": "alive"
})

// The command returns an object with the following structure
//
// {
// 	"acknowledged" : true,
// 	"insertedId" : 10
// }
```

Notice how the second document we inserted (`pinky`) has an extra field (`status`). MongoDB allows us to have a lot of flexibility with the schema, but we should be careful with it.

### insertMany()

[db.collection.insertMany()](https://docs.mongodb.com/v3.2/reference/method/db.collection.insertMany/) allows us to insert more than one document at the same time. `insertMany()` receives an array of documents as a paramater.

**Example**

```javascript
> db.enemies.insertMany([
     {
        "name": "Inky",
        "color": "Cyan",
     },
     {
        "name": "Clyde",
        "color": "Orange"
     }
])

// The command returns an object with the following structure
//
// {
// 	"acknowledged" : true,
// 	"insertedIds" : [
// 		ObjectId("583c645b6fa7d619e2c574e7"),
// 		ObjectId("583c645b6fa7d619e2c574e8")
// 	]
// }
```
The return object will have a key `insertedIds`, which contains an array with the `ids` of the inserted elements

### About insert()

The [db.collection.insert()](https://docs.mongodb.com/v3.2/reference/method/db.collection.insert/) method inserts a single document in the same way that `insertOne()` does.

:::danger
:bomb: **Warning Notice**

The [insert](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#insert) method is deprecated (should not be used because it will be removed soon) in the **Node.js mongo driver**. You can use it in MongoShell, but we strongly recommend to use the `insertOne` and `insertMany` methods above in order to get used to the syntax.
:::


## Read | Finding/Listing Documents

The idea behind the read operation is that we should be able to retrieve `documents` from the database and read their contents. The basic method to find documents is [db.collection.find()](https://docs.mongodb.com/v3.2/reference/method/db.collection.find/) where you can specify two optional arguments:

:::info
`db.collection.find( <query_filter>, <projection> )`
:::

- `<query_filter>` an object that specifies which documents to return 
- `<projection>` an object that allows us to return only certain fields from those documents

![](https://i.imgur.com/aCPgpwr.png)

### Query Filters

#### Select all documents

To get all documents from a collection is as simple as specifying an empty object as the first argument.

```
> db.enemies.find({})
```

:::info
:bulb: If we only pass one argument we can omit the empty object. `db.enemies.find()` is the same as `db.enemies.find({})`
:::

#### Specify Equality Condition

Equality conditions will select all documents where the `<field>` matches the exact `<value>`

```
> db.collection.find({<field>: <value>})
```

**Example:**
```
> db.enemies.find({"name": "Blinky"})
```

:::warning
:cactus: Keep in mind that `<value>` is case sensitive, so `'Blinky'` is not the same as `'blinky'`.
:::

#### Advanced Conditions

We can specify conditions like greater than or less than, to do so  we use query operators like:

```javascript
> db.collection.find(
    { <field>: { <operator>: <value>} }
  )
```

Mongo provides us with a comprehensive list of [query operators](https://docs.mongodb.com/manual/reference/operator/query/), but for now, let's look at some of the most useful ones:

Mongo Operators | Description
:----------------:|-----------------
`$eq`  | equal to
`$ne`  | not equal to
`$gt`  | greater than
`$gte` | greater than equal
`$lt`  | less than
`$lte` | less than equal

**Example**

Imagine that we have a collection where documents have the following structure:

```javascript
[
  { name: "Popeye",       age: 30 },
  { name: "Mickey Mouse", age: 35 },
  { name: "Batman",       age: 24 }
]
```

If we want to select all the users who are older than 32 years, we can do the following query.

```
db.user.find({"age": { $gt: 32 }})
```

### Limiting Fields | Projections

The Find method's second argument, which we mentioned earlier, is called a [projection](https://docs.mongodb.com/v3.2/tutorial/project-fields-from-query-results/), and it allows us to specify which fields should be returned from each document in the result.

:::info
**Using projections makes our database queries faster**. When MongoDB has to retrieve less fields, it's less work for the computer to do and less information to transfer over the network so the query takes less time.
:::

Let's see how to use the projection.

The projection must be an object with either:

- All the fields we want to include (set them to `1`) 
- All the fields we want to exclude (set them to `0`) 
 
The projection cannot combine `0` and `1` at the same time except for the `_id` that can be `0` when others are `1`.

:::warning
By default "_id" is set to `1`, so if we don't want to show it we have to specify `_id: 0`.
:::

Example:
```javascript
> db.enemies.find({},{
    "name": 1,
    "_id": 0
})
```
As you can see we specified as a projection {`"name": 1`, `"_id": 0`}. Mongo will return the `name` property of each documents, but not their `_id`:


```javascript
{ "name" : "Blinky" }
{ "name" : "Pinky" }
{ "name" : "Inky" }
{ "name" : "Clyde" }
```

### Independent Practice

Let's introduce the following documents to our database so that we can all start with the same data.

```javascript
{
 name: "Sue",
 age: 19,
 phone: {
  personal: "555-123-123",
  work: "555-456-456",
  ext: "2342"
 },
 privileges: "user",
 favorites: { artist: "Picasso", food: "pizza" },
 finished: [ 17, 3 ],
 badges: [ "blue", "black" ],
 points: [
    { points: 85, bonus: 20 },
    { points: 85, bonus: 10 }
 ]
},
{
 name: "Bob",
 age: 42,
 phone: {
  personal: "555-123-123",
  work: "555-456-456",
  ext: "7673"
 },
 privileges: "admin",
 favorites: { artist: "Miro", food: "meringue" },
 finished: [ 11, 25 ],
 badges: [ "green" ],
 points: [
    { points: 85, bonus: 20 },
    { points: 64, bonus: 12 }
 ]
},
{
 name: "Willy",
 age: 22,
 phone: {
  personal: "555-123-123",
  work: "555-456-456",
  ext: "8263"
 },
 privileges: "user",
 favorites: { artist: "Cassatt", food: "cake" },
 finished: [ 6 ],
 badges: [ "blue", "Picasso" ],
 points: [
    { points: 81, bonus: 8 },
    { points: 55, bonus: 20 }
 ]
},
{
 name: "John",
 age: 34,
 phone: {
  personal: "555-123-123",
  work: "555-456-456",
  ext: "2143"
 },
 privileges: "admin",
 favorites: { artist: "Chagall", food: "chocolate" },
 finished: [ 5, 11 ],
 badges: [ "Picasso", "black" ],
 points: [
    { points: 53, bonus: 15 },
    { points: 51, bonus: 15 }
 ]
},
{
 name: "Steve",
 age: 23,
 phone: {
  personal: "555-123-123",
  work: "555-456-456",
  ext: "8253"
 },
 privileges: "user",
 favorites: { artist: "Noguchi", food: "nougat" },
 finished: [ 14, 6 ],
 badges: [ "orange" ],
 points: [
    { points: 71, bonus: 20 }
 ]
},
{
 name: "Martin",
 age: 43,
 phone: {
  personal: "555-123-123",
  work: "555-456-456",
  ext: "5623"
 },
 privileges: "user",
 favorites: { food: "pizza", artist: "Picasso" },
 finished: [ 18, 12 ],
 badges: [ "black", "blue" ],
 points: [
    { points: 78, bonus: 8 },
    { points: 57, bonus: 7 }
 ]
}
```

Open your mongoshell, introduce the documents above in the collection `employees` and perform the following queries:

- List all the employees
- Find the employee with whose name is Steve
- Find all employees whose age is greater than 30
- Find the employee whose extension is 2143

*(Should take approximately 10 minutes)*


## Update commands

The update command allows us to update some fields in the document or replace all document:

| Mongo Method | Description
|--------------|---------------------
| [`db.collection.updateOne(<filter>, <update>)`](https://docs.mongodb.com/v3.2/reference/method/db.collection.updateOne/) | Updates a single document within the collection
| [`db.collection.updateMany(<filter>, <update>)`](https://docs.mongodb.com/v3.2/reference/method/db.collection.updateMany/) | Updates multiple documents within the collection
| [`db.collection.replaceOne(<filter>, <update>)`](https://docs.mongodb.com/v3.2/reference/method/db.collection.replaceOne/) | Replaces a single document within the collection

All these methods accept two parameters:
- `<filter>`  finds what documents to update (same as [query filters](https://hackmd.io/mGLw7B34Q7a0GfnaaqfQmw#Query-Filters))
- `<update>` specifies what fields to update in the document

:::info lecture
Bien se référer à la [doc Mongo](https://docs.mongodb.com/v3.2/reference/method/db.collection.updateOne/).
:::

### updateOne()

[db.collection.updateOne()](https://docs.mongodb.com/v3.2/reference/method/db.collection.updateOne/) updates a single document that matches the specified filter.

:::warning
:warning: If we have more than one document that matches that filter, this operation will update only one.
:::

Following with the collection `employees`, let's update the user `"Martin"` with his new extension number.

```javascript
db.employees.updateOne(
  { "name": "Martin"},
  { $set: { "phone.ext": 1234 }}
)
```
This function will return an object where `"matchedCount"` is how many documents satisfy the filter and `"modifiedCount"` is how many documents were updated.

:::warning
:warning: Notice that when we need to access nested objects like the `ext` field inside `phone`, we need to use dot notation like JavaScript objects. They have to be in double quotes: `"phone.ext"`:

```javascript
{
 name: "Martin",
 age: 43,
 phone: {
   personal: "555-123-123",
   work: "555-456-456",
   ext: "5623"
 },
 privileges: "user",
 favorites: { food: "pizza", artist: "Picasso" },
 finished: [ 18, 12 ],
 badges: [ "black", "blue" ],
 points: [
    { points: 78, bonus: 8 },
    { points: 57, bonus: 7 }
 ]
}
```
:::

```javascript
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
```

**Your turn!** Try to update the age of Sue to 20.


### updateMany() 

[db.collection.updateMany()](https://docs.mongodb.com/v3.2/reference/method/db.collection.updateMany/) updates all documents that match the specified filter.

We want to update all employees older than 30 so that their favourite writer is Cervantes.

```javascript
db.employees.updateMany(
  { "age": { $gte: 30 }},
	{ $set: { "favorites.writer": "Cervantes" }}
)
```
Result:
```javascript
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 3 }
```

### replaceOne()

[db.collection.replaceOne()](https://docs.mongodb.com/v3.2/reference/method/db.collection.replaceOne/) replaces the first document that matches the specified filter even if there are more than one.

Our employee `"Martin"` is not working anymore in our company so let's replace him for our new employee `"Susan"`.

The new document for `"Susan"`
```javascript
var susan = { 
  "name" : "Susan",
  "age" : 25,
  "phone" : { "personal" : "555-223-223", "work" : "555-421-426", "ext" : 4240 },
  "privileges" : "user",
}

db.employees.replaceOne(
  { "name": "Martin"},
  susan
)
```

:::info
:bulb: Replacing a document does not change its `_id` value. The `_id` field is immutable. If we include it in the new document it must have the same value as before.
:::


## Delete commands

The delete commands remove documents from our collections.

### deleteOne()

```javascript
db.employees.deleteOne( { "_id": ObjectId("583ea82c58613b64d5df8405") })
```

### deleteMany()

If we want to remove **all** documents

```javascript
db.employees.deleteMany({})
```

Removes the documents that match the filter criteria.

```javascript
db.employees.deleteMany({ age : { $gte: 30 }})
```

## Independent Practice

Now that you know how to insert, delete, query and update documents, let's practice!

- Find all employees that are over 30.
- Find all employees that are less than or equal to 30.
- Find all the employees whose favorite food is pizza.
- Change Willy's personal phone number to "93-123-45-67".
- Change Bob's privilege to normal user.
- Find all employees whose favorite artist is equal to Picasso.
- Delete the user John.
- (EXTRA) Add a bonus of 15 to all those who have a bonus less than 10.

## Summary

In this lesson we learnt how to perform basic operations with MongoShell.

## Extra Resources

- [Mongo CRUD Documentation](https://docs.mongodb.com/v3.2/crud/)
- [Query selectors in MongoDB](https://docs.mongodb.com/v3.2/reference/operator/query/#query-selectors)
- [Reference Operators](https://docs.mongodb.com/v3.2/reference/)