原教學:https://www.callicoder.com/node-js-express-mongodb-restful-crud-api-tutorial/
原做者:Rajeev Singhhtml
你們好,我是小志,也能夠叫我Jason。前端
該文章不是對原文進行翻譯,只是記錄本身的一些想法。node
一直沒有用過MongoDB,想學習和了解一下NoSQL要如何運做,該如何進行CRUD等操做,找了一篇教學,發現十分簡單,記錄一下本身的學習路程。git
學習目的:用Node.js和Express創建一個Restful API, 能夠對數據進行CRUD的操做mongodb
先安裝MongoDB, https://docs.mongodb.com/manual/administration/install-community/
我本身是WINDOW安裝的,基本上就是下載MSI,而後下一步接下一步,最後等他安裝完就好。express
工具:
Express用下來的感受是輕便簡單,沒有太多複雜的操做(最少這裏用到的沒有)npm
Mongoose對MongoDB操做的工具,更詳細的說法請看原教學json
測試工具:
Postman 對API進行測試的工具, 發送各類request後端
最後項目的結構
下面漸進式完成整個項目的構建api
開一個文件夾,例如:
node-easy-notes-app
初始化NPM
npm init
name: (node-easy-notes-app) version: (1.0.0) description: Never miss a thing in Life. Take notes quickly. Organize and keep track of all your notes. entry point: (index.js) server.js test command: git repository: keywords: Express RestAPI MongoDB Mongoose Notes author: callicoder license: (ISC) MIT About to write to /Users/rajeevkumarsingh/node-easy-notes-app/package.json: { "name": "node-easy-notes-app", "version": "1.0.0", "description": "Never miss a thing in Life. Take notes quickly. Organize and keep track of all your notes.", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "Express", "RestAPI", "MongoDB", "Mongoose", "Notes" ], "author": "callicoder", "license": "MIT" } Is this ok? (yes) yes
比較須要留意的是,定義了項目的entry point.
在下面運行的時候,會以server.js做爲入口,運行整個程序。
安裝express, body-parser, mongoose
npm install express body-parser mongoose --save
目前結構
node-easy-notes-app └── node_modules/ └── package.json
在ROOT下,開一個server.js的文件,複製下面的內容
const express = require('express'); const bodyParser = require('body-parser'); // 建立express app const app = express(); // parse requests of content-type - application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: true })) // parse requests of content-type - application/json app.use(bodyParser.json()) // define a simple route app.get('/', (req, res) => { res.json({"message": "Welcome to EasyNotes application. Take notes quickly. Organize and keep track of all your notes."}); }); // listen for requests app.listen(3000, () => { console.log("Server is listening on port 3000"); });
上面的內容定義了一個簡單的服務器
監聽3000端口
bodyParser是用來存取request和response的工具
$ node server.js Server is listening on port 3000
正常運行的話,會看到上面監聽3000端口的內容
console.log("Server is listening on port 3000");
一個簡單的Express Server就創建起來了。
能夠經過localhost:3000來訪問
{ "message": "Welcome to EasyNotes application. Take notes quickly. Organize and keep track of all your notes." }
先創建好文件夾
config裏database.config.js放MongoDB鏈接的URL
module.exports = { url: 'mongodb://localhost:27017/easy-notes' }
在server.js的app.use(bodyParser.json())後面,複製下面的代碼,用於鏈接MongoDB
// Configuring the database const dbConfig = require('./config/database.config.js'); const mongoose = require('mongoose'); mongoose.Promise = global.Promise; // Connecting to the database mongoose.connect(dbConfig.url, { useNewUrlParser: true, //Solve DeprecationWarning useFindAndModify: false, useUnifiedTopology: true }).then(() => { console.log("Successfully connected to the database"); }).catch(err => { console.log('Could not connect to the database. Exiting now...', err); process.exit(); });
這一段是爲了不DeprecationWarning
//Solve DeprecationWarning useFindAndModify: false, useUnifiedTopology: true
app/models/note.model.js
const mongoose = require('mongoose'); const NoteSchema = mongoose.Schema({ title: String, content: String }, { timestamps: true }); module.exports = mongoose.model('Note', NoteSchema);
經過mongoose定義Note的Schema
options: {timestamps: true}
自動添加了createdAt和updatedAt
相對於relational database方便了很多,並且不用特地去寫SQL建立表格
雖然也用過JAVA的hibernate可是感受別限制的死死的,很不方便。(剛入職的時候,我的能力也不是很強,去看在用hibernate的老項目,實在捉急)
app/routes/note.route.js
module.exports = (app) => { const notes = require('../controllers/note.controller.js'); // Create a new Note app.post('/notes', notes.create); // Retrieve all Notes app.get('/notes', notes.findAll); // Retrieve a single Note with noteId app.get('/notes/:noteId', notes.findOne); // Update a Note with noteId app.put('/notes/:noteId', notes.update); // Delete a Note with noteId app.delete('/notes/:noteId', notes.delete); }
這邊先寫route,是由於controller包括CRUD,會比較長,因此先寫route
從route也能看到一些controller的功能
create, findAll, findOne, update, delete
route只不過是把
post, get, put,delete
跟controller鏈接起來
app/controllers/note.controller.js
const Note = require('../models/note.model.js'); // Create and Save a new Note exports.create = (req, res) => { // Validate request if(!req.body.content) { return res.status(400).send({ message: "Note content can not be empty" }); } // Create a Note const note = new Note({ title: req.body.title || "Untitled Note", content: req.body.content }); // Save Note in the database note.save() .then(data => { res.send(data); }).catch(err => { res.status(500).send({ message: err.message || "Some error occurred while creating the Note." }); }); }; // Retrieve and return all notes from the database. exports.findAll = (req, res) => { Note.find() .then(notes => { res.send(notes); }).catch(err => { res.status(500).send({ message: err.message || "Some error occurred while retrieving notes." }); }); }; // Find a single note with a noteId // Find a single note with a noteId exports.findOne = (req, res) => { Note.findById(req.params.noteId) .then(note => { if(!note) { return res.status(404).send({ message: "Note not found with id " + req.params.noteId }); } res.send(note); }).catch(err => { if(err.kind === 'ObjectId') { return res.status(404).send({ message: "Note not found with id " + req.params.noteId }); } return res.status(500).send({ message: "Error retrieving note with id " + req.params.noteId }); }); }; // Update a note identified by the noteId in the request exports.update = (req, res) => { // Validate Request if(!req.body.content) { return res.status(400).send({ message: "Note content can not be empty" }); } // Find note and update it with the request body Note.findByIdAndUpdate(req.params.noteId, { title: req.body.title || "Untitled Note", content: req.body.content }, {new: true}) .then(note => { if(!note) { return res.status(404).send({ message: "Note not found with id " + req.params.noteId }); } res.send(note); }).catch(err => { if(err.kind === 'ObjectId') { return res.status(404).send({ message: "Note not found with id " + req.params.noteId }); } return res.status(500).send({ message: "Error updating note with id " + req.params.noteId }); }); }; // Delete a note with the specified noteId in the request exports.delete = (req, res) => { Note.findByIdAndRemove(req.params.noteId) .then(note => { if(!note) { return res.status(404).send({ message: "Note not found with id " + req.params.noteId }); } res.send({message: "Note deleted successfully!"}); }).catch(err => { if(err.kind === 'ObjectId' || err.name === 'NotFound') { return res.status(404).send({ message: "Note not found with id " + req.params.noteId }); } return res.status(500).send({ message: "Could not delete note with id " + req.params.noteId }); }); };
導入note.model.js使用Mongoose的API 進行CRUD的操做
其中
findByIdAndUpdate( :id, data:{...}, options:{new: true} ).then( options.new ?updatedNote :originalNote )
options:{new: true}說的是回傳的note會是更新狀態後的Note
若是不定義,或者new: false
則會回傳還沒更新的Note.
Mongoose API
最後用Postman對API進行測試
超簡單的Restful API接口就寫好了
測試部分就不費篇章敘述了,下一個目標是用Vue+ElementUI去把前端寫起來,再擴張一下這個後端,寫一個比較簡單的先後端結合的項目。
我是小志,也能夠叫我Jason,謝謝觀看。