在本教程中,我们将使用 Node.js、Express 和 MongoDB 构建一个 RESTful CRUD(创建、检索、更新、删除)API。我们将使用 Mongoose 与 MongoDB 实例进行交互。
Express 是最流行的 node.js 网络框架之一。它建立在 node.js http 模块之上,并增加了对路由、中间件、视图系统等的支持。它非常简单和最小,不像其他框架那样做太多,从而降低了开发人员使用他们的灵活性自己的设计选择。
Mongoose 是 Node.js 和 MongoDB 的 ODM(对象文档映射)工具。它可以帮助您将代码中的对象转换为数据库中的文档,反之亦然。
在继续下一节之前,如果您还没有安装 MongoDB,请在您的机器上安装。查看 official MogngoDB installation manual 以获取有关安装的任何帮助。
###我们的应用程序
在本教程中,我们将构建一个简单的笔记应用程序。我们将构建用于创建、列出、编辑和删除笔记的 Rest API。
我们将从构建一个简单的 Web 服务器开始,然后继续配置数据库,构建 Note
模型和处理所有 CRUD 操作的不同路由。
最后,我们将使用 Postman 测试我们的 REST API。
此外,在这篇文章中,我们将大量使用 ES6 特性,如 let
、const
、arrow functions
、promises
等。熟悉这些是很好的特征。我推荐 this re-introduction to Javascript 来复习这些概念。
好!现在我们知道我们要构建什么,我们需要为我们的应用程序取一个很酷的名字。让我们调用我们的应用程序 EasyNotes
。
1.启动您的终端并为应用程序创建一个新文件夹。
$ mkdir node-easy-notes-app
2.使用 package.json 文件初始化应用程序
转到应用程序的根文件夹并键入 npm init
以使用 package.json
文件初始化您的应用程序。
$ cd node-easy-notes-app
$ 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
请注意,我指定了一个名为 server.js
的文件作为我们应用程序的入口点。我们将在下一节中创建 server.js
文件。
3.安装依赖
我们将在我们的应用程序中需要 express、mongoose 和 body-parser 模块。让我们通过键入以下命令来安装它们 -
$ npm install express body-parser mongoose --save
我使用 --save
选项将所有依赖项保存在 package.json
文件中。最终的 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",
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.3",
"mongoose": "^5.2.8"
}
}
我们的应用程序文件夹现在有一个 package.json
文件和一个 node_modules
文件夹 -
node-easy-notes-app
└── node_modules/
└── package.json
现在让我们创建应用程序的主要入口点。在应用程序的根文件夹中创建一个名为 server.js
的新文件,内容如下 -
const express = require('express');
const bodyParser = require('body-parser');
// create 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");
});
首先,我们导入 express 和 body-parser 模块。如您所知,Express 是我们将用于构建 REST API 的 Web 框架,body-parser 是一个模块,用于解析(各种内容类型的)请求并创建一个req.body
我们可以在路由中访问的对象。
然后,我们创建一个 express 应用,并使用 express 的 app.use()
方法添加两个 body-parser
中间件。 middleware 是一个可以访问 request
和 response
对象的函数。它可以执行任何代码、转换请求对象或返回响应。
**然后,**我们定义了一个简单的 GET
路由,它向客户端返回一条欢迎消息。
最后, 我们在端口 3000 上侦听传入连接。
好的!现在让我们运行服务器并转到 http://localhost:3000
访问我们刚刚定义的路由。
$ node server.js
Server is listening on port 3000
我喜欢将应用程序的所有配置保存在一个单独的文件夹中。让我们在应用程序的根文件夹中创建一个新文件夹 config
来保存所有配置 -
$ mkdir config
$ cd config
现在,在 config
文件夹中创建一个新文件 database.config.js
,内容如下:
module.exports = {
url: 'mongodb://localhost:27017/easy-notes'
}
我们现在将在 server.js
中导入上述数据库配置并使用 mongoose 连接到数据库。
在 app.use(bodyParser.json())
行之后的 server.js
文件中添加以下代码 -
// 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
}).then(() => {
console.log("Successfully connected to the database");
}).catch(err => {
console.log('Could not connect to the database. Exiting now...', err);
process.exit();
});
请运行服务器并确保您能够连接到数据库 -
$ node server.js
Server is listening on port 3000
Successfully connected to the database
接下来,我们将定义 Note
模型。在应用程序的根文件夹中创建一个名为 app
的新文件夹,然后在 app
文件夹中创建另一个名为 models
的文件夹 -
$ mkdir -p app/models
$ cd app/models
现在,在 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);
Note
模型非常简单。它包含一个 title
和一个 content
字段。我还在架构中添加了一个时间戳选项。
Mongoose 使用此选项自动向架构添加两个新字段 - createdAt
和 updatedAt
。
接下来是 Notes API 的路由。在 app
文件夹中创建一个名为 routes
的新文件夹。
$ mkdir app/routes
$ cd app/routes
现在,在 app/routes
文件夹中创建一个名为 note.routes.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);
}
请注意,我们为 note.controller.js
文件添加了 require
语句。我们将定义控制oller 文件在下一节。控制器将包含处理所有 CRUD 操作的方法。
在定义控制器之前,让我们首先在 server.js
中包含路由。在 server.js 文件中的 app.listen()
行之前添加以下 require
语句。
// ........
// Require Notes routes
require('./app/routes/note.routes.js')(app);
// ........
如果你现在运行服务器,你会得到以下错误 -
$ node server.js
module.js:472
throw err;
^
Error: Cannot find module '../controllers/note.controller.js'
这是因为我们还没有定义控制器。让我们现在就这样做。
在 app
文件夹中创建一个名为 controllers
的新文件夹,然后在 app/controllers
文件夹中创建一个名为 note.controller.js
的新文件,内容如下:
const Note = require('../models/note.model.js');
// Create and Save a new Note
exports.create = (req, res) => {
};
// Retrieve and return all notes from the database.
exports.findAll = (req, res) => {
};
// Find a single note with a noteId
exports.findOne = (req, res) => {
};
// Update a note identified by the noteId in the request
exports.update = (req, res) => {
};
// Delete a note with the specified noteId in the request
exports.delete = (req, res) => {
};
现在我们来一一看看上述控制器功能的实现——
// 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
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
});
});
};
findByIdAndUpdate()
方法中的 {new: true}
选项用于将修改后的文档返回给 then()
函数而不是原始文档。
// 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
});
});
};
您可以在 Mongoose 的官方文档中查看我们在上述 API 中使用的所有方法的文档 -
*猫鼬保存()
*猫鼬查找()
现在让我们使用 postman 一一测试所有 API。
POST /notes
API 创建新笔记GET /notes
API 检索所有笔记GET /notes/:noteId
API 检索单个笔记PUT /notes/:noteId
API 更新笔记DELETE /notes/:noteId
API 删除笔记版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.callicoder.com/node-js-express-mongodb-restful-crud-api-tutorial/
内容来源于网络,如有侵权,请联系作者删除!