Skip to content

Exercises 7 : MongoDB (20p)

Remember use JAMK/GitLab to return your exercises. Student need to test that exercise really work.

Exercise 01 - Account [5p]

Create an own account to MongoDB Atlas Cloud. Follow Mongo materials and create test database and persons collection. Add a few documents to person collection (use your own name and other information in there too). Install MongoDB Compass application and make a connection to your MongoDB Atlas Cloud.

Return a few screenshots which shows your test database and persons collection with your documents in MongoDB Atlas Cloud and MongoDB Compass.

Exercise 02 - Shell [5p]

Follow and test examples given in MongoDB materials - Using MongoDB Compass Mongo Shell. Make 5 of your own modifications to shown examples. Use MongoDB Compass shell.

Return text files or screenshots which clearly shows your own 5 modifications.

Exercise 03 - REST API [10p]

Introduction

Modify the Users REST API task of the Express exercises to use the MongoDB database.

Tip

Take a copy of the previous version and use another copy. Thus, you will keep both versions!

Delete the users JSON sample data used in the previous task:

1
2
3
4
5
// let users = 
// [
//   { 'id':'1', 'name':'Kirsi Kernel' },
//   { 'id':'2', 'name':'Matti Mainio' }
// ]

Mongoose

MongoDB can be accessed directly using Node.js's Mongo driver library, but it's a bit hard. The Mongoose library is available for this purpose. Through Mongoose, JavaScript objects can be saved directly as Mongo documents.

You are going to use the Mongoose ODM to access our persons data. Mongoose will act as a front end to MongoDB. This ODM (Object Data Model) and database combination is extremely popular in the Node community. Document storage and queries looks very much like JSON and it is familiar to JavaScript developers.

Install Mongoose module to your project:

1
npm install mongoose

Connection to database

Find your own connection string to MongoDB Atlas Cloud and use it in your index.js file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
const express = require('express') 
const app = express()
app.use(express.json())
const port = 3000

// use mongoose
const mongoose = require('mongoose')

// connection string - EDIT YOUR OWN HERE
const mongoDB = 'mongodb+srv://pasi:password@democluster.brlob.mongodb.net/myFirstDatabase?retryWrites=true&w=majority'

// connect mongodb
mongoose.connect(mongoDB, {useNewUrlParser: true, useUnifiedTopology: true})
const db = mongoose.connection

// check connection - ok or error
db.on('error', console.error.bind(console, 'connection error:'))
db.once('open', function() {
  console.log("Database test connected")
})

Save the changes and if you are using Nodemon you should see the connection success or failure on your console.

1
2
3
4
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
Example app listening on port 3000
Database test connected

Mongoose Schema

Models are defined using the Schema interface. The Schema allows you to define the fields stored in each document along with their validation requirements and default values.

Add the following Schema to the beginning of the index.js file after the Mongo connection. Now the user object has only the name value.

1
2
3
4
// new schema
const userSchema = new mongoose.Schema({
  name: String
})

Now created schema is very simply. Note that it can be very informative. The personSchema used in the example below defines the name value as a string and mandatory. Age must be typed as a number with a minimum value of 0.

1
2
3
4
5
const personSchema = new mongoose.Schema({
  name: { type: String, required: true },
  age: { type: Number, min: 0 },
  email: String
})

Tip

You should check Mongoose validation syntax to learn more how to create powerful schemas.

Schemas are compiled into models using the mongoose.model(). Once you have a model you can use it to find, create, update, and delete objects of the given type to your database.

Mongoose Model

Add a new User model to your use.

1
2
// new model
const User = mongoose.model('User', userSchema, 'users')

POST route/endpoint

In the Express exercise, JSON data (users) was only stored in memory on the Node.js server. The post route used in that exercise created a new users object and added it to the JSON data (users).

1
2
3
4
5
6
7
app.post('/users/', (request, response) => {
  const maxId = Math.max(...users.map(user => user.id), 0)
  const user = request.body
  user.id = (maxId+1).toString() 
  users = users.concat(user) 
  response.json(user)
})

Modify post route to add new data to MongoDB.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// create a new user
app.post('/users', async (request, response) => {
  // Get name from request
  const { name } = request.body

  // Create a new user
  const user = new User({
    name: name
  })

  // Save to db and send back to caller
  const savedUser = await user.insertOne()
  response.json(savedUser)  
})

Send a post request using Visual Studio's REST Client or Postman. Check that the sent user information has been added to your database.

The example below uses Visual Studio to send the request:

1
2
3
4
5
6
POST http://localhost:3000/users
Content-Type: application/json

{
  "name": "Matt Markuson"
}

Check that your database shows the first user document. Note that MongoDB generates a unique id for the document.

Image 01

Add some user objects to your MongoDB database. Check the contents of the MongoDB database.

GET route/endpoint

Change the get route so that the data is fetched from the MongoDB database.

1
2
3
4
5
// get all users
app.get('/users', async (request, response) => {
  const users = await User.find({})
  response.json(users)
})

Also change the returning route of one user object as follows:

1
2
3
4
5
6
// get one user
app.get('/users/:id', async (request, response) => {
  const user = await User.findById(request.params.id)
  if (user) response.json(user)
  else response.status(404).end()
})

DELETE route/endpoint

Change the delete path to delete data from the MongoDB database:

1
2
3
4
5
6
// delete one user
app.delete('/users/:id', async (request, response) => {
  const deletedUser = await User.findByIdAndRemove(request.params.id)
  if (deletedUser) response.json(deletedUser)
  else response.status(404).end()
})

The exercise is returned by pointing to the URL to the source codes of the program and to 2-4 screenshots showing the operation of your programs.