#1 – What is MongoDB?
In this series you’ll learn how to use MongoDB (a NoSQL database) from scratch. You’ll also learn how to integrate it into a simple Node.js API.
#2 – Installing MongoDB
Learn how to install MongoDB locally onto your computer.
#3 – Collections & Documents
#4 – Using MongoDB Compass
#5 – Using the MongoDB Shell
指令
- show dbs
- use database’s
使用其他終端機 – 指令
- mongosh
- cls
- db
- show collections
- help
- exit
#6 – Adding New Documents
指令
// insertOne
db.books.insertOne({title: "The Color of Magic", author: "Terry Pratchett", pages: 300, rating: 7, genres: ["fantasy", "magic"]})
// insertMany
db.books.insertMany([{title: "The Light Fantastic", author: "Terry Pratchett", pages: 250, rating: 6, genres: ["fantasy"]}, {title: "Dune", author: "Frank Herbert", pages: 500, rating: 10, genres: ["sci-fi", "dystopian"]}])
#7 – Finding Documents
指令
- db.books.find()
- db.books.find({author: “Terry Pratchett”})
- db.books.find({author: “Terry Pratchett”, rating: 7})
- db.books.find({author: “Brandon Sanderson”})
- db.books.find({author: “Brandon Sanderson”}, {title: 1, author: 1})
- db.books.find({}, {title: 1, author: 1})
- db.books.find({_id: ObjectId(“650be28b103e76e586910c81”)})
#8 – Sorting & Limiting Data
指令
- db.books.find().count()
- db.books.find({ author: “Brandon Sanderson” }).count()
- db.books.find().limit(3)
- db.books.find().limit(3).count()
- db.books.find().sort({ title: 1 })
- db.books.find().sort({ title: -1 })
- db.books.find().sort({ title: 1 }).limit(3)
#9 – Nested Documents
指令
// insertOne
db.books.insertOne({title: "The Way of Kings", author: "Brandon Sanderson", rating: 9, pages: 400, genres: ["fantasy"], reviews: [{name: "Yoshi", body: "Great book!!"}, {name: "mario", body: "so so"}]})
// insertMany
db.books.insertMany([{title: "The Light Fantastic", author: "Terry Pratchett", pages: 250, rating: 6, genres: ["fantasy", "magic"], reviews: [{name:"luigi", body: "it was pretty good"}, {name: "bowser", body: "loved it!!"}]}, {title: "The Name of the Wind", "author": "Patrick Rothfuss", page: 500, "rating": 10, genres: ["fantasy"], review: [{name: "peach", body: "one of my favs"}]}, {title: "The Color of Magic", "author": "Terry Pratchett", page: 350, "rating": 8, genres: ["fantasy", "magic"], review: [{name: "luigi", body: "it was ok"}, {name: "bowser", body: "really good book"}]}, {title: "1984", "author": "George Orwell", page: 300, "rating": 6, genres: ["sci-fi", "dystopian"], review: [{name: "peach", body: "not my cup of tea"}, {name: "mario", body: "meh"}]}])
#10 – Operators & Complex Queries
指令
- db.books.find({rating: 7})
- db.books.find({ rating: {$gt: 7}})
- db.books.find({ rating: {$gt: 8}})
- db.books.find({ rating: {$lte: 8}})
- db.books.find({ rating: {$gte: 8}})
- db.books.find({ rating: {$gt: 7}, author: “Patrick Rothfuss”})
- db.books.find({$or: [{rating: 7}, {rating: 9}]})
- db.books.find({$or: [{rating: 7}, {author: “Terry Pratchett”}]})
- db.books.find({$or: [{pages: {$lt: 300}}, {pages: {$gt: 400}}]})
#11 – Using $in & $nin
指令
- db.books.find({ rating: {$in: [7,8,9]}})
- db.books.find({$or: [{rating: 7}, {rating: 8}, {rating: 9}]})
- db.books.find({rating: {$nin: [7,8,9]}})
- db.books.find({rating: {$nin: [7,8]}})
#12 – Querying Arrays
指令
- db.books.find({genres: “fantasy”})
- db.books.find({genres: “magic”})
- db.books.find({genres: [“magic”]})
- db.books.find({genres: [“fantasy”]})
- db.books.find({genres: [“fantasy”, “magic”]})
- db.books.find({genres: {$all: [“fantasy”, “sci-fi”]}})
- db.books.find({“reviews.name”: “luigi”})
#13 – Deleting Documents
事先使用 MongoDB Compass EXPORT DATA 把資料匯出成JSON檔案。
指令
- db.books.find()
- db.books.deleteOne({_id: ObjectId(“650d22be248ed3d1c20642d0”)})
- db.books.deleteMany({author: “Terry Pratchett”})
使用 MongoDB Compass ADD DATA 把檔案匯入。
#14 – Updating Documents
指令
- db.books.updateOne({_id: ObjectId(“650d22be248ed3d1c20642cf”)}, {$set: {rating: 8, pages: 360}})
- db.books.updateMany({author: “Terry Pratchett”}, {$set: {author: “Terry Pratchet”}})
- db.books.updateOne({_id: ObjectId(“650d22be248ed3d1c20642d0”)}, {$inc: {pages: 2}})
- db.books.updateOne({_id: ObjectId(“650d22be248ed3d1c20642d0”)}, {$inc: {pages: -2}})
- db.books.updateOne({_id: ObjectId(“650d22be248ed3d1c20642d0”)}, {$pull: {genres: “fantasy”}})
- db.books.updateOne({_id: ObjectId(“650d22be248ed3d1c20642d0”)}, {$push: {genres: “fantasy”}})
- db.books.updateOne({_id: ObjectId(“650d22be248ed3d1c20642d0”)}, {$push: {genres: {$each: [“1″,”2”]}}})
#15 – MongoDB Drivers
指令 & 操作步驟
- npm init
- 建立一個 app.js 檔案
- npm install express –save
- npm install -g nodemon
- nodemon app
- http://localhost:3000/books
- 新增終端 npm install mongodb –save
// app.js
const express = require('express')
// init app & middleware
const app = express()
app.listen(3000, () => {
console.log('app listening on port 3000')
})
// routes
app.get('/books', (req, res) => {
res.json({mssg: "welcome to the api"})
})
#16 – Connecting to MongoDB
操作步驟
- 建立一個 db.js 檔案
- 修改 app.js 檔案內容
// db.js
const { MongoClient } = require('mongodb')
let dbConnection
module.exports = {
connectToDb: (cb) => {
MongoClient.connect('mongodb://localhost:27017/bookstore')
.then((client) => {
dbConnection = client.db()
return cb()
})
.catch(err => {
console.log(err)
return cb(err)
})
},
getDb: () => dbConnection
}
// app.js
const express = require('express')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
res.json({mssg: "welcome to the api"})
})
#17 – Cursors & Fetching Data
操作步驟
- 繼續修改 app.js 檔案內容
// app.js
const express = require('express')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
let books = []
db.collection('books')
.find()
.sort({ author: 1 })
.forEach(book => books.push(book))
.then(() => {
res.status(200).json(books)
})
.catch(() => {
res.status(500).json({error: 'Could not fetch the documents'})
})
})
#18 – Finding Single Documents
操作步驟
- 繼續修改 app.js
- 使用 URL 測試是否能正常找到單一文件 http://localhost:3000/books/650d22be248ed3d1c20642cf
- 增加一些 ObjectId 布林判斷 app.js
// app.js - 1
const express = require('express')
const { ObjectId } = require('mongodb')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
let books = []
db.collection('books')
.find()
.sort({ author: 1 })
.forEach(book => books.push(book))
.then(() => {
res.status(200).json(books)
})
.catch(() => {
res.status(500).json({error: 'Could not fetch the documents'})
})
})
app.get('/books/:id', (req, res) => {
db.collection('books')
.findOne({_id: new ObjectId(req.params.id)})
.then(doc => {
res.status(200).json(doc)
})
.catch(err => {
res.status(500).json({error: 'Could not fetch the document'})
})
})
// app.js -3
const express = require('express')
const { ObjectId } = require('mongodb')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
let books = []
db.collection('books')
.find()
.sort({ author: 1 })
.forEach(book => books.push(book))
.then(() => {
res.status(200).json(books)
})
.catch(() => {
res.status(500).json({error: 'Could not fetch the documents'})
})
})
app.get('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.findOne({_id: new ObjectId(req.params.id)})
.then(doc => {
res.status(200).json(doc)
})
.catch(err => {
res.status(500).json({error: 'Could not fetch the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
#19 – Using POSTMAN
Request
- http://localhost:3000/books
- http://localhost:3000/books/650d1421248ed3d1c20642cc
#20 – Handling POST Request
操作步驟
- 在 app.js 新增 post 相關程式碼
- 使用 POSTMAN 請求 POST 方法
- http://localhost:3000/books
- Body > raw 貼上準備好的資料內容然後送出
- 可以看到 Response Body 呈現的訊息
- 點擊之前的 Get Collection – books 測試
// app.js
const express = require('express')
const { ObjectId } = require('mongodb')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
app.use(express.json())
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
let books = []
db.collection('books')
.find()
.sort({ author: 1 })
.forEach(book => books.push(book))
.then(() => {
res.status(200).json(books)
})
.catch(() => {
res.status(500).json({error: 'Could not fetch the documents'})
})
})
app.get('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.findOne({_id: new ObjectId(req.params.id)})
.then(doc => {
res.status(200).json(doc)
})
.catch(err => {
res.status(500).json({error: 'Could not fetch the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
app.post('/books', (req, res) => {
const book = req.body
db.collection('books')
.insertOne(book)
.then(result => {
res.status(201).json(result)
})
.catch(err => {
res.status(500).json({err: 'Could not create a new document'})
})
})
// Body > raw JSON
{
"title": "The Final Empire",
"author": "Brandon Sanderson",
"rating": 9,
"pages": 420,
"genres": [
"fantasy",
"magic"
],
"reviews": [
{
"name": "Shaun",
"body": "Couldn't put this book down."
},
{
"name": "Chun-Li",
"body": "Love it."
}
]
}
#21 – Handling DELETE Requests
操作步驟
- 在 app.js 新增 delete 相關程式碼
- 使用 POSTMAN 請求 DELETE 方法
- http://localhost:3000/books/650d22be248ed3d1c20642d0
- 送出後可以看到 Response Body 的訊息
- 點擊 Get 方法查看是否有刪除資料
// app.js
const express = require('express')
const { ObjectId } = require('mongodb')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
app.use(express.json())
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
let books = []
db.collection('books')
.find()
.sort({ author: 1 })
.forEach(book => books.push(book))
.then(() => {
res.status(200).json(books)
})
.catch(() => {
res.status(500).json({error: 'Could not fetch the documents'})
})
})
app.get('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.findOne({_id: new ObjectId(req.params.id)})
.then(doc => {
res.status(200).json(doc)
})
.catch(err => {
res.status(500).json({error: 'Could not fetch the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
app.post('/books', (req, res) => {
const book = req.body
db.collection('books')
.insertOne(book)
.then(result => {
res.status(201).json(result)
})
.catch(err => {
res.status(500).json({err: 'Could not create a new document'})
})
})
app.delete('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.deleteOne({_id: new ObjectId(req.params.id)})
.then(result => {
res.status(200).json(result)
})
.catch(err => {
res.status(500).json({error: 'Could not delete the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
#22 – PATCH Requests
操作步驟
- 在 app.js 新增 PATCH 相關程式碼
- 使用 POSTMAN 請求 PATCH 方法
- 因為出現錯誤,有重新 import bookstore.books 檔案
- http://localhost:3000/books/650d1421248ed3d1c20642cc
- Body > raw JSON 更新資料後送出會呈現 Body 訊息
- 使用 GET Collection 查看是否有正確更新
// app.js
const express = require('express')
const { ObjectId } = require('mongodb')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
app.use(express.json())
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
let books = []
db.collection('books')
.find()
.sort({ author: 1 })
.forEach(book => books.push(book))
.then(() => {
res.status(200).json(books)
})
.catch(() => {
res.status(500).json({error: 'Could not fetch the documents'})
})
})
app.get('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.findOne({_id: new ObjectId(req.params.id)})
.then(doc => {
res.status(200).json(doc)
})
.catch(err => {
res.status(500).json({error: 'Could not fetch the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
app.post('/books', (req, res) => {
const book = req.body
db.collection('books')
.insertOne(book)
.then(result => {
res.status(201).json(result)
})
.catch(err => {
res.status(500).json({err: 'Could not create a new document'})
})
})
app.delete('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.deleteOne({_id: new ObjectId(req.params.id)})
.then(result => {
res.status(200).json(result)
})
.catch(err => {
res.status(500).json({error: 'Could not delete the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
app.patch('/books/:id', (req, res) => {
const updates = req.body
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.updateOne({_id: new ObjectId(req.params.id)}, {$set: updates})
.then(result => {
res.status(200).json(result)
})
.catch(err => {
res.status(500).json({error: 'Could not update the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
Body > raw JSON
{
"pages": 350,
"rating": 8
}
#23 – Pagination
In this MongoDB tutorial I’ll explain how to implement pagination into your requests.
操作步驟
- 在 app.js 新增關於 pagination 程式碼
- 使用 POSTMAN 請求 GET 方法
以下兩種結果會相同 - http://localhost:3000/books
- http://localhost:3000/books?p=0
- 使用 http://localhost:3000/books?p=1
會忽略前面的資料 - http://localhost:3000/books?p=2
因為沒有資料會出現空陣列
// app.js
const express = require('express')
const { ObjectId } = require('mongodb')
const { connectToDb, getDb } = require('./db')
// init app & middleware
const app = express()
app.use(express.json())
// db connection
let db
connectToDb((err) => {
if (!err) {
app.listen(3000, () => {
console.log('app listening on port 3000')
})
db = getDb()
}
})
// routes
app.get('/books', (req, res) => {
// current page
const page = req.query.p || 0
const booksPerPage = 3
let books = []
db.collection('books')
.find()
.sort({ author: 1 })
.skip(page * booksPerPage)
.limit(booksPerPage)
.forEach(book => books.push(book))
.then(() => {
res.status(200).json(books)
})
.catch(() => {
res.status(500).json({error: 'Could not fetch the documents'})
})
})
app.get('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.findOne({_id: new ObjectId(req.params.id)})
.then(doc => {
res.status(200).json(doc)
})
.catch(err => {
res.status(500).json({error: 'Could not fetch the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
app.post('/books', (req, res) => {
const book = req.body
db.collection('books')
.insertOne(book)
.then(result => {
res.status(201).json(result)
})
.catch(err => {
res.status(500).json({err: 'Could not create a new document'})
})
})
app.delete('/books/:id', (req, res) => {
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.deleteOne({_id: new ObjectId(req.params.id)})
.then(result => {
res.status(200).json(result)
})
.catch(err => {
res.status(500).json({error: 'Could not delete the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
app.patch('/books/:id', (req, res) => {
const updates = req.body
if (ObjectId.isValid(req.params.id)) {
db.collection('books')
.updateOne({_id: new ObjectId(req.params.id)}, {$set: updates})
.then(result => {
res.status(200).json(result)
})
.catch(err => {
res.status(500).json({error: 'Could not update the document'})
})
} else {
res.status(500).json({error: 'Not a valid doc id'})
}
})
#24 – Indexes
In this mongodb tutorial we’ll talk about indexes and see how to create them.
簡報
- db.collection(“books”).find({“rating”: 10})
指令 & 操作步驟
- 使用終端機執行 mongosh
- 使用 bookstore 資料庫 use bookstore
- db.books.find({rating: 8}).explain(‘executionStats’)
- db.books.createIndex({ rating: 8 })
- db.books.getIndexes()
- db.books.dropIndex({rating: 8})
- db.books.getIndexes()
#25 – MongoDB Atlas
In this mongodb tutorial you’ll learn how to use MongoDB Atlas, a Cloud Database service which allows you to easily set up a hosted database online.
操作步驟
- 註冊或登入 MongoDB
- DEPLOYMENT > Database 選擇建立一個 Database
- 選擇 Shared 免費方案
- aws > default 或者自行選擇 > Cluster Name 默認原本名稱 > 建立 Cluster
- Security Quickstart 可以設定 Username 和 Password
- 設定好後可以到 Database Access 查看
- Network Access > 新增一個 IP address > 在這裡選擇 ALLOW ACCESS FROM ANYWHERE 僅作測試使用,之後生產版本請勿選擇這個選項
- 到 Database Deployment 點擊 Connection > 選擇 Connect your application
- Add your connection string into your application code
- 在 db.js 修改成指定的 connection string > 修改設定的 Username 和 Password
- 我們不需要修改這些 Request,我們仍然使用這些 Request 關於 localhost
- Mongodb online 資料庫尚未有任何資料 > 可以 post 新的資料到線上資料庫 > Browse Collections
// db.js
const { MongoClient } = require('mongodb')
let dbConnection
let uri = '指定的 connection string'
module.exports = {
connectToDb: (cb) => {
MongoClient.connect(uri)
.then((client) => {
dbConnection = client.db()
return cb()
})
.catch(err => {
console.log(err)
return cb(err)
})
},
getDb: () => dbConnection
}