原教学: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,谢谢观看。