使用MongoDB在Alibaba Cloud上创建Node.js REST API的方法是什么
本文将探讨如何在阿里巴巴云上利用MongoDB和Node.js创建强大的REST API。
阿里巴巴云拥有两个数据中心在日本,并拥有超过60个可用区域,是亚太地区的领先云基础设施服务提供商(根据2019年Gartner数据)。欲了解更多阿里巴巴云的详情,请访问阿里巴巴云官方网页。
安装MongoDB在阿里巴巴云ECS上。安装MongoDB很容易。
パッケージ名説明mongodb-org以下の4つのコンポーネントパッケージを自動的にインストールするメタパッケージです。mongodb-org-serverデーモンと関連する設定スクリプトと init スクリプトが含まれています。mongodb-org-mongosデーモンが含まれています。mongodb-org-shellシェルが含まれています。mongodb-org-tools以下の MongoDB ツールが含まれています: mongoimport bsondump, mongodump, mongoexport, mongofiles, mongorestore, mongostat, and mongotop.mongodb-org-server 包提供了在 /etc/mongod.conf 配置文件中启动 mongod 的初始化脚本。
请按照以下步骤使用此链接在ECS Ubuntu服务器上安装MongoDB:https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
安装完成后,您可以开始构建简单的REST API。
REST API in Chinese can be paraphrased as “REST 应用程序接口” (REST .REST是Representational State Transfer的首字母缩写。最近,REST API非常流行,并且被用于处理Web应用程序和移动应用程序的服务器端。实际上,大多数知名的互联网公司都引入了至少一些REST API,比如Google日历API。一旦数据库建立好了,就可以使用API轻松地将数据和内容传递给应用程序。这些API表示服务器如何对请求做出响应和接受,以实现CRUD(创建、读取、更新、删除)过程。在本教程中,我们将构建一个简单的API,使其可以发布问题、回答问题,并在可扩展的MongoDB上对回答进行投票和删除。成功实现项目的关键在于正确组织路由。在此情况下,路由将被编程如下。
1、分析投稿的问题
2、阅读、创建、编辑、删除答案
3、对答案进行投票赞成或反对
在这个例子中,情况如下。
开发环境在这个项目中,我们使用以下工具。
1、纯粹的JavaScript
2、Node.js
3、Express(JavaScript框架)
4、MongoDB(数据库)
5、Yarn(包管理工具)
6、Visual Studio Code作为编辑器
7、Postman(用于测试API终点)
相互依赖使用所需的依赖包
1、解析器(解析受信端点请求的正文)
2、Express(启动应用程序)
3、Nodemon(重新启动服务器以反映更改)
4、Mongoose(使用对象数据模型简化与 MongoDB 的交互)
5、Morgan(将 HTTP 请求记录到日志中的中间件)
6、Eslint with Airbnb(是用于辅助创建高质量代码的扩展功能)
教程总结在这个例子中,我们将执行以下操作。
1、使用 Express 创建 API 路由
2、建模 API 数据
3、使用 Mongoose 连接 MongoDB
4、使用 Postman 清理和测试 API
用Express构建API路由。
基本的事情 de要简化开发过程,你可以安装nodemon,并在package.json的脚本中添加命令。
1、使用express创建基本的Web服务器(express有此过程的教程)。
2、确保Express中间件配置灵活。
3、包括用于处理请求的body-parser。
4、将解析器整合到Express中间件中。
创建一个供提问使用的路径1、在服务器上创建存储根目录的文件。
2、使用POST和GET两个路由来搜索问题并添加新问题。
3、创建具体问题的GET路由。
router.get('/', (req, res) => {
res.json({ response: 'a GET request for LOOKING at questions' });
});
router.post('/', (req, res) => {
res.json({
response: 'a POST request for CREATING questions',
body: req.body
});
});
router.get('/:qID', (req, res) => {
res.json({
response: `a GET request for LOOKING at a special answer id: ${req.params.qID}`
});
});
回答路径 lù)1、首先,要安装Morgan HTTP请求记录器。 这个软件包有助于您分析请求。
2、然后,创建一个POST路由来接受回应。
3、接下来,包括PUT和DELETE以使编辑和删除回应成为可能。
4、创建用于回应上投票和下投票的POST路由(在本教程中使用简单的投票)。
router.post('/:qID/answers', (req, res) => {
res.json({
response: 'a POST request for CREATING answers',
question: req.params.qID,
body: req.body
});
});
router.put('/:qID/answers/:aID', (req, res) => {
res.json({
response: 'a PUT request for EDITING answers',
question: req.params.qID,
answer: req.params.aID,
body: req.body
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
res.json({
response: 'a DELETE request for DELETING answers',
question: req.params.qID,
answer: req.params.aID,
body: req.body
});
});
router.post('/:qID/answers/:aID/vote-:dec', (req, res) => {
res.json({
response: 'a POST request for VOTING on answers',
question: req.params.qID,
answer: req.params.aID,
vote: req.params.dec,
body: req.body
});
});
错误处理器几乎不可能避免任何应用程序出错。在这个例子中,我们将按照以下步骤设置错误处理器。
1、中间件作为 “错误捕捉器” 来运作。
2、在捕捉到 404 错误后,使用中间件将其传递给自定义处理程序以JSON响应格式进行回应(否则,会使用500错误)。
3、设置验证中间件,使错误的上投票和下投票成为可能。
app.use((req, res, next) => {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
error: {
message: err.message
}
});
});
使用 Mongoose 连接到 MongoDB。
选择API的数据模型在MongoDB的存储中,选择的数据类型必须清晰地表示正确的结构和关系非常重要。Mongoose作为连接到MongoDB的网关起作用。它用于创建接受JSON数据格式的模式。在这种情况下,使用具有回答属性的问题对象是最佳方法。然而,要记住Mongo文档中存储单元的最大数量,因此对于问题的回答并非无限制。
创建模式1、根据所选的父子结构,在Mongoose中创建适当的模式。
2、利用模式构建模型。
const AnswerSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
votes: { type: Number, default: 0 }
});
const QuestionSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
answers: [AnswerSchema]
});
const Question = mongoose.model('Question', QuestionSchema);
在功能中添加排序和投票选项
1、优先考虑最新的答案。
2、在答案模式中包含保存投票选项。
3、指示Mongoose在预先排序的同时保存所有答案。
4、使用parent方法,使回答与问题的父文档相关联。
5、避免在规范中使用箭头函数。
const sortAnswers = (a, b) => {
if (a.votes === b.votes) {
return b.updatedAt - a.updatedAt;
}
return b.votes - a.votes;
};
QuestionSchema.pre('save', function (next) {
this.answers.sort(sortAnswers);
next();
});
AnswerSchema.method('update', function (updates, callback) {
Object.assign(this, updates, { updatedAt: new Date() });
this.parent().save(callback);
});
AnswerSchema.method('vote', function (vote, callback) {
if (vote === 'up') {
this.votes += 1;
} else {
this.votes -= 1;
}
this.parent().save(callback);
});
将API连接到MongoDB你正在尝试解决我认为最困难的任务。请现在仔细查看Mongoose的文档。
错误处理1、在这种情况下,我们将使用param方法来带有qID和aID回调的根目录。
2、此方法可以识别在数据库中无法使用问题或答案的情况下的错误。
router.param('qID', (req, res, next, id) => {
Question.findById(id, (err, doc) => {
if (err) return next(err);
if (!doc) {
err = new Error('Document not found');
err.status = 404;
return next(err);
}
req.question = doc;
return next();
});
});
router.param('aID', (req, res, next, id) => {
req.answer = req.question.answers.id(id);
if (!req.answer) {
err = new Error('Answer not found');
err.status = 404;
return next(err);
}
return next();
});
准备问题路线1、这将使用GET路由在Mongo数据库中检索问题。
2、返回相应的问题。
3、同时,使用POST路由将新问题以JSON格式发布到数据库。
4、为每个问题指定一个GET路由。
router.get('/', (req, res, next) => {
Question.find({}).sort({ createdAt: -1 }).exec((err, questions) => {
if (err) return next(err);
res.json(questions);
});
});
router.post('/', (req, res) => {
const question = new Question(req.body);
question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.get('/:qID', (req, res) => {
res.json(req.question);
});
更新答案的途径1、执行创建回答的POST的操作非常简单。在这个方法中,将答案推送到问题文档中并以JSON格式保存。
2、使用update方法可以通过返回新的JSON输入来更新答案。
3、因此,如果要使用DELETE路由删除答案,则使用remove方法。
4、对于投票,可以使用嵌入在中间件中的POST路由,在vote方法中保存投票。
以下示例对此操作进行了说明。
router.post('/:qID/answers', (req, res, next) => {
req.question.answers.push(req.body);
req.question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.put('/:qID/answers/:aID', (req, res, next) => {
req.answer.update(req.body, (err, result) => {
if (err) return next(err);
res.json(result);
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
req.answer.remove(err => {
req.question.save((err, question) => {
if (err) return next(err);
res.json(question);
});
});
});
router.post(
'/:qID/answers/:aID/vote-:dec',
(req, res, next) => {
if (req.params.dec.search(/^(up|down)$/) === -1) {
const err = new Error(`Not possible to vot for ${req.params.dec}!`);
err.status = 404;
next(err);
} else {
req.vote = req.params.dec;
next();
}
},
(req, res, next) => {
req.answer.vote(req.vote, (err, question) => {
if (err) return next(err);
res.json(question);
});
}
);
现在,REST API将开始被使用。现在,REST API已经准备就绪可以被使用了。接下来进入下一个阶段。
清理和测试终端点
API的测试在测试所有的终端点功能时,最简单的方法是使用Postman。您可以使用Chrome扩展或者下载桌面应用程序来实现。无论选择哪个方式都可以,但我个人更喜欢使用Chrome扩展。Postman的使用方法很简单,可以进行HTTP测试。如果您不想手动测试,还可以设置自动化测试。
跨源资源共享出于安全考虑,CORS受到了限制。基本上,它是允许浏览器访问域资源的方法。因此,需要通过以下步骤使用中间件来实现从域中消费API的功能。
1、所有的来源都需要有访问首部的权限。
2、使HTTP请求有效。
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
if (req.method === 'Options') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, DELETE');
return res.status(200).json({});
}
});
开始前端工作你的API已经配置好,可以与任何类型的前端连接。使用正确的头信息和路径,进行提交、获取、设置和删除操作同样简单。
總結REST API是一种非常好用的工具,可以用于设置可扩展的后端微服务。在这个项目中,我们使用Mongoose在可扩展的开源数据库MongoDB上实现了一个简单的API。让我们尝试使用阿里巴巴云在MongoDB上运行移动应用程序。希望您喜欢这篇文章。
阿里巴巴云已在日本建立了两个数据中心,并拥有超过60个可用区,被誉为2019年亚太地区No.1(根据Gartner)的云基础设施提供商。
欲了解更多阿里巴巴云的详细信息,请点击此处查看阿里巴巴云日本官方页面。
请按照以下步骤使用此链接在ECS Ubuntu服务器上安装MongoDB:https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
安装完成后,您可以开始构建简单的REST API。
REST API in Chinese can be paraphrased as “REST 应用程序接口” (REST .REST是Representational State Transfer的首字母缩写。最近,REST API非常流行,并且被用于处理Web应用程序和移动应用程序的服务器端。实际上,大多数知名的互联网公司都引入了至少一些REST API,比如Google日历API。一旦数据库建立好了,就可以使用API轻松地将数据和内容传递给应用程序。这些API表示服务器如何对请求做出响应和接受,以实现CRUD(创建、读取、更新、删除)过程。在本教程中,我们将构建一个简单的API,使其可以发布问题、回答问题,并在可扩展的MongoDB上对回答进行投票和删除。成功实现项目的关键在于正确组织路由。在此情况下,路由将被编程如下。
1、分析投稿的问题
2、阅读、创建、编辑、删除答案
3、对答案进行投票赞成或反对
在这个例子中,情况如下。
开发环境在这个项目中,我们使用以下工具。
1、纯粹的JavaScript
2、Node.js
3、Express(JavaScript框架)
4、MongoDB(数据库)
5、Yarn(包管理工具)
6、Visual Studio Code作为编辑器
7、Postman(用于测试API终点)
相互依赖使用所需的依赖包
1、解析器(解析受信端点请求的正文)
2、Express(启动应用程序)
3、Nodemon(重新启动服务器以反映更改)
4、Mongoose(使用对象数据模型简化与 MongoDB 的交互)
5、Morgan(将 HTTP 请求记录到日志中的中间件)
6、Eslint with Airbnb(是用于辅助创建高质量代码的扩展功能)
教程总结在这个例子中,我们将执行以下操作。
1、使用 Express 创建 API 路由
2、建模 API 数据
3、使用 Mongoose 连接 MongoDB
4、使用 Postman 清理和测试 API
用Express构建API路由。
基本的事情 de要简化开发过程,你可以安装nodemon,并在package.json的脚本中添加命令。
1、使用express创建基本的Web服务器(express有此过程的教程)。
2、确保Express中间件配置灵活。
3、包括用于处理请求的body-parser。
4、将解析器整合到Express中间件中。
创建一个供提问使用的路径1、在服务器上创建存储根目录的文件。
2、使用POST和GET两个路由来搜索问题并添加新问题。
3、创建具体问题的GET路由。
router.get('/', (req, res) => {
res.json({ response: 'a GET request for LOOKING at questions' });
});
router.post('/', (req, res) => {
res.json({
response: 'a POST request for CREATING questions',
body: req.body
});
});
router.get('/:qID', (req, res) => {
res.json({
response: `a GET request for LOOKING at a special answer id: ${req.params.qID}`
});
});
回答路径 lù)1、首先,要安装Morgan HTTP请求记录器。 这个软件包有助于您分析请求。
2、然后,创建一个POST路由来接受回应。
3、接下来,包括PUT和DELETE以使编辑和删除回应成为可能。
4、创建用于回应上投票和下投票的POST路由(在本教程中使用简单的投票)。
router.post('/:qID/answers', (req, res) => {
res.json({
response: 'a POST request for CREATING answers',
question: req.params.qID,
body: req.body
});
});
router.put('/:qID/answers/:aID', (req, res) => {
res.json({
response: 'a PUT request for EDITING answers',
question: req.params.qID,
answer: req.params.aID,
body: req.body
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
res.json({
response: 'a DELETE request for DELETING answers',
question: req.params.qID,
answer: req.params.aID,
body: req.body
});
});
router.post('/:qID/answers/:aID/vote-:dec', (req, res) => {
res.json({
response: 'a POST request for VOTING on answers',
question: req.params.qID,
answer: req.params.aID,
vote: req.params.dec,
body: req.body
});
});
错误处理器几乎不可能避免任何应用程序出错。在这个例子中,我们将按照以下步骤设置错误处理器。
router.get('/', (req, res) => {
res.json({ response: 'a GET request for LOOKING at questions' });
});
router.post('/', (req, res) => {
res.json({
response: 'a POST request for CREATING questions',
body: req.body
});
});
router.get('/:qID', (req, res) => {
res.json({
response: `a GET request for LOOKING at a special answer id: ${req.params.qID}`
});
});
2、然后,创建一个POST路由来接受回应。
3、接下来,包括PUT和DELETE以使编辑和删除回应成为可能。
4、创建用于回应上投票和下投票的POST路由(在本教程中使用简单的投票)。
router.post('/:qID/answers', (req, res) => {
res.json({
response: 'a POST request for CREATING answers',
question: req.params.qID,
body: req.body
});
});
router.put('/:qID/answers/:aID', (req, res) => {
res.json({
response: 'a PUT request for EDITING answers',
question: req.params.qID,
answer: req.params.aID,
body: req.body
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
res.json({
response: 'a DELETE request for DELETING answers',
question: req.params.qID,
answer: req.params.aID,
body: req.body
});
});
router.post('/:qID/answers/:aID/vote-:dec', (req, res) => {
res.json({
response: 'a POST request for VOTING on answers',
question: req.params.qID,
answer: req.params.aID,
vote: req.params.dec,
body: req.body
});
});
错误处理器几乎不可能避免任何应用程序出错。在这个例子中,我们将按照以下步骤设置错误处理器。
1、中间件作为 “错误捕捉器” 来运作。
2、在捕捉到 404 错误后,使用中间件将其传递给自定义处理程序以JSON响应格式进行回应(否则,会使用500错误)。
3、设置验证中间件,使错误的上投票和下投票成为可能。
app.use((req, res, next) => {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
error: {
message: err.message
}
});
});
使用 Mongoose 连接到 MongoDB。
选择API的数据模型在MongoDB的存储中,选择的数据类型必须清晰地表示正确的结构和关系非常重要。Mongoose作为连接到MongoDB的网关起作用。它用于创建接受JSON数据格式的模式。在这种情况下,使用具有回答属性的问题对象是最佳方法。然而,要记住Mongo文档中存储单元的最大数量,因此对于问题的回答并非无限制。
创建模式1、根据所选的父子结构,在Mongoose中创建适当的模式。
2、利用模式构建模型。
const AnswerSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
votes: { type: Number, default: 0 }
});
const QuestionSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
answers: [AnswerSchema]
});
const Question = mongoose.model('Question', QuestionSchema);
在功能中添加排序和投票选项
1、优先考虑最新的答案。
2、在答案模式中包含保存投票选项。
3、指示Mongoose在预先排序的同时保存所有答案。
4、使用parent方法,使回答与问题的父文档相关联。
5、避免在规范中使用箭头函数。
const sortAnswers = (a, b) => {
if (a.votes === b.votes) {
return b.updatedAt - a.updatedAt;
}
return b.votes - a.votes;
};
QuestionSchema.pre('save', function (next) {
this.answers.sort(sortAnswers);
next();
});
AnswerSchema.method('update', function (updates, callback) {
Object.assign(this, updates, { updatedAt: new Date() });
this.parent().save(callback);
});
AnswerSchema.method('vote', function (vote, callback) {
if (vote === 'up') {
this.votes += 1;
} else {
this.votes -= 1;
}
this.parent().save(callback);
});
将API连接到MongoDB你正在尝试解决我认为最困难的任务。请现在仔细查看Mongoose的文档。
错误处理1、在这种情况下,我们将使用param方法来带有qID和aID回调的根目录。
2、此方法可以识别在数据库中无法使用问题或答案的情况下的错误。
router.param('qID', (req, res, next, id) => {
Question.findById(id, (err, doc) => {
if (err) return next(err);
if (!doc) {
err = new Error('Document not found');
err.status = 404;
return next(err);
}
req.question = doc;
return next();
});
});
router.param('aID', (req, res, next, id) => {
req.answer = req.question.answers.id(id);
if (!req.answer) {
err = new Error('Answer not found');
err.status = 404;
return next(err);
}
return next();
});
准备问题路线1、这将使用GET路由在Mongo数据库中检索问题。
2、返回相应的问题。
3、同时,使用POST路由将新问题以JSON格式发布到数据库。
4、为每个问题指定一个GET路由。
router.get('/', (req, res, next) => {
Question.find({}).sort({ createdAt: -1 }).exec((err, questions) => {
if (err) return next(err);
res.json(questions);
});
});
router.post('/', (req, res) => {
const question = new Question(req.body);
question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.get('/:qID', (req, res) => {
res.json(req.question);
});
更新答案的途径1、执行创建回答的POST的操作非常简单。在这个方法中,将答案推送到问题文档中并以JSON格式保存。
2、使用update方法可以通过返回新的JSON输入来更新答案。
3、因此,如果要使用DELETE路由删除答案,则使用remove方法。
4、对于投票,可以使用嵌入在中间件中的POST路由,在vote方法中保存投票。
以下示例对此操作进行了说明。
router.post('/:qID/answers', (req, res, next) => {
req.question.answers.push(req.body);
req.question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.put('/:qID/answers/:aID', (req, res, next) => {
req.answer.update(req.body, (err, result) => {
if (err) return next(err);
res.json(result);
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
req.answer.remove(err => {
req.question.save((err, question) => {
if (err) return next(err);
res.json(question);
});
});
});
router.post(
'/:qID/answers/:aID/vote-:dec',
(req, res, next) => {
if (req.params.dec.search(/^(up|down)$/) === -1) {
const err = new Error(`Not possible to vot for ${req.params.dec}!`);
err.status = 404;
next(err);
} else {
req.vote = req.params.dec;
next();
}
},
(req, res, next) => {
req.answer.vote(req.vote, (err, question) => {
if (err) return next(err);
res.json(question);
});
}
);
创建模式1、根据所选的父子结构,在Mongoose中创建适当的模式。
2、利用模式构建模型。
const AnswerSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
votes: { type: Number, default: 0 }
});
const QuestionSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
answers: [AnswerSchema]
});
const Question = mongoose.model('Question', QuestionSchema);
在功能中添加排序和投票选项
1、优先考虑最新的答案。
2、在答案模式中包含保存投票选项。
3、指示Mongoose在预先排序的同时保存所有答案。
4、使用parent方法,使回答与问题的父文档相关联。
5、避免在规范中使用箭头函数。
const sortAnswers = (a, b) => {
if (a.votes === b.votes) {
return b.updatedAt - a.updatedAt;
}
return b.votes - a.votes;
};
QuestionSchema.pre('save', function (next) {
this.answers.sort(sortAnswers);
next();
});
AnswerSchema.method('update', function (updates, callback) {
Object.assign(this, updates, { updatedAt: new Date() });
this.parent().save(callback);
});
AnswerSchema.method('vote', function (vote, callback) {
if (vote === 'up') {
this.votes += 1;
} else {
this.votes -= 1;
}
this.parent().save(callback);
});
将API连接到MongoDB你正在尝试解决我认为最困难的任务。请现在仔细查看Mongoose的文档。
错误处理1、在这种情况下,我们将使用param方法来带有qID和aID回调的根目录。
2、此方法可以识别在数据库中无法使用问题或答案的情况下的错误。
router.param('qID', (req, res, next, id) => {
Question.findById(id, (err, doc) => {
if (err) return next(err);
if (!doc) {
err = new Error('Document not found');
err.status = 404;
return next(err);
}
req.question = doc;
return next();
});
});
router.param('aID', (req, res, next, id) => {
req.answer = req.question.answers.id(id);
if (!req.answer) {
err = new Error('Answer not found');
err.status = 404;
return next(err);
}
return next();
});
准备问题路线1、这将使用GET路由在Mongo数据库中检索问题。
2、返回相应的问题。
3、同时,使用POST路由将新问题以JSON格式发布到数据库。
4、为每个问题指定一个GET路由。
router.get('/', (req, res, next) => {
Question.find({}).sort({ createdAt: -1 }).exec((err, questions) => {
if (err) return next(err);
res.json(questions);
});
});
router.post('/', (req, res) => {
const question = new Question(req.body);
question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.get('/:qID', (req, res) => {
res.json(req.question);
});
更新答案的途径1、执行创建回答的POST的操作非常简单。在这个方法中,将答案推送到问题文档中并以JSON格式保存。
2、使用update方法可以通过返回新的JSON输入来更新答案。
3、因此,如果要使用DELETE路由删除答案,则使用remove方法。
4、对于投票,可以使用嵌入在中间件中的POST路由,在vote方法中保存投票。
以下示例对此操作进行了说明。
router.post('/:qID/answers', (req, res, next) => {
req.question.answers.push(req.body);
req.question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.put('/:qID/answers/:aID', (req, res, next) => {
req.answer.update(req.body, (err, result) => {
if (err) return next(err);
res.json(result);
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
req.answer.remove(err => {
req.question.save((err, question) => {
if (err) return next(err);
res.json(question);
});
});
});
router.post(
'/:qID/answers/:aID/vote-:dec',
(req, res, next) => {
if (req.params.dec.search(/^(up|down)$/) === -1) {
const err = new Error(`Not possible to vot for ${req.params.dec}!`);
err.status = 404;
next(err);
} else {
req.vote = req.params.dec;
next();
}
},
(req, res, next) => {
req.answer.vote(req.vote, (err, question) => {
if (err) return next(err);
res.json(question);
});
}
);
const AnswerSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
votes: { type: Number, default: 0 }
});
const QuestionSchema = new Schema({
text: String,
createdAt: { type: Date, default: Date.now },
answers: [AnswerSchema]
});
const Question = mongoose.model('Question', QuestionSchema);
1、优先考虑最新的答案。
2、在答案模式中包含保存投票选项。
3、指示Mongoose在预先排序的同时保存所有答案。
4、使用parent方法,使回答与问题的父文档相关联。
5、避免在规范中使用箭头函数。
const sortAnswers = (a, b) => {
if (a.votes === b.votes) {
return b.updatedAt - a.updatedAt;
}
return b.votes - a.votes;
};
QuestionSchema.pre('save', function (next) {
this.answers.sort(sortAnswers);
next();
});
AnswerSchema.method('update', function (updates, callback) {
Object.assign(this, updates, { updatedAt: new Date() });
this.parent().save(callback);
});
AnswerSchema.method('vote', function (vote, callback) {
if (vote === 'up') {
this.votes += 1;
} else {
this.votes -= 1;
}
this.parent().save(callback);
});
将API连接到MongoDB你正在尝试解决我认为最困难的任务。请现在仔细查看Mongoose的文档。
错误处理1、在这种情况下,我们将使用param方法来带有qID和aID回调的根目录。
2、此方法可以识别在数据库中无法使用问题或答案的情况下的错误。
router.param('qID', (req, res, next, id) => {
Question.findById(id, (err, doc) => {
if (err) return next(err);
if (!doc) {
err = new Error('Document not found');
err.status = 404;
return next(err);
}
req.question = doc;
return next();
});
});
router.param('aID', (req, res, next, id) => {
req.answer = req.question.answers.id(id);
if (!req.answer) {
err = new Error('Answer not found');
err.status = 404;
return next(err);
}
return next();
});
准备问题路线1、这将使用GET路由在Mongo数据库中检索问题。
2、返回相应的问题。
3、同时,使用POST路由将新问题以JSON格式发布到数据库。
4、为每个问题指定一个GET路由。
router.get('/', (req, res, next) => {
Question.find({}).sort({ createdAt: -1 }).exec((err, questions) => {
if (err) return next(err);
res.json(questions);
});
});
router.post('/', (req, res) => {
const question = new Question(req.body);
question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.get('/:qID', (req, res) => {
res.json(req.question);
});
更新答案的途径1、执行创建回答的POST的操作非常简单。在这个方法中,将答案推送到问题文档中并以JSON格式保存。
2、使用update方法可以通过返回新的JSON输入来更新答案。
3、因此,如果要使用DELETE路由删除答案,则使用remove方法。
4、对于投票,可以使用嵌入在中间件中的POST路由,在vote方法中保存投票。
以下示例对此操作进行了说明。
router.post('/:qID/answers', (req, res, next) => {
req.question.answers.push(req.body);
req.question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.put('/:qID/answers/:aID', (req, res, next) => {
req.answer.update(req.body, (err, result) => {
if (err) return next(err);
res.json(result);
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
req.answer.remove(err => {
req.question.save((err, question) => {
if (err) return next(err);
res.json(question);
});
});
});
router.post(
'/:qID/answers/:aID/vote-:dec',
(req, res, next) => {
if (req.params.dec.search(/^(up|down)$/) === -1) {
const err = new Error(`Not possible to vot for ${req.params.dec}!`);
err.status = 404;
next(err);
} else {
req.vote = req.params.dec;
next();
}
},
(req, res, next) => {
req.answer.vote(req.vote, (err, question) => {
if (err) return next(err);
res.json(question);
});
}
);
2、此方法可以识别在数据库中无法使用问题或答案的情况下的错误。
router.param('qID', (req, res, next, id) => {
Question.findById(id, (err, doc) => {
if (err) return next(err);
if (!doc) {
err = new Error('Document not found');
err.status = 404;
return next(err);
}
req.question = doc;
return next();
});
});
router.param('aID', (req, res, next, id) => {
req.answer = req.question.answers.id(id);
if (!req.answer) {
err = new Error('Answer not found');
err.status = 404;
return next(err);
}
return next();
});
准备问题路线1、这将使用GET路由在Mongo数据库中检索问题。
2、返回相应的问题。
3、同时,使用POST路由将新问题以JSON格式发布到数据库。
4、为每个问题指定一个GET路由。
router.get('/', (req, res, next) => {
Question.find({}).sort({ createdAt: -1 }).exec((err, questions) => {
if (err) return next(err);
res.json(questions);
});
});
router.post('/', (req, res) => {
const question = new Question(req.body);
question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.get('/:qID', (req, res) => {
res.json(req.question);
});
更新答案的途径1、执行创建回答的POST的操作非常简单。在这个方法中,将答案推送到问题文档中并以JSON格式保存。
2、使用update方法可以通过返回新的JSON输入来更新答案。
3、因此,如果要使用DELETE路由删除答案,则使用remove方法。
4、对于投票,可以使用嵌入在中间件中的POST路由,在vote方法中保存投票。
以下示例对此操作进行了说明。
router.post('/:qID/answers', (req, res, next) => {
req.question.answers.push(req.body);
req.question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.put('/:qID/answers/:aID', (req, res, next) => {
req.answer.update(req.body, (err, result) => {
if (err) return next(err);
res.json(result);
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
req.answer.remove(err => {
req.question.save((err, question) => {
if (err) return next(err);
res.json(question);
});
});
});
router.post(
'/:qID/answers/:aID/vote-:dec',
(req, res, next) => {
if (req.params.dec.search(/^(up|down)$/) === -1) {
const err = new Error(`Not possible to vot for ${req.params.dec}!`);
err.status = 404;
next(err);
} else {
req.vote = req.params.dec;
next();
}
},
(req, res, next) => {
req.answer.vote(req.vote, (err, question) => {
if (err) return next(err);
res.json(question);
});
}
);
router.get('/', (req, res, next) => {
Question.find({}).sort({ createdAt: -1 }).exec((err, questions) => {
if (err) return next(err);
res.json(questions);
});
});
router.post('/', (req, res) => {
const question = new Question(req.body);
question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.get('/:qID', (req, res) => {
res.json(req.question);
});
2、使用update方法可以通过返回新的JSON输入来更新答案。
3、因此,如果要使用DELETE路由删除答案,则使用remove方法。
4、对于投票,可以使用嵌入在中间件中的POST路由,在vote方法中保存投票。
以下示例对此操作进行了说明。
router.post('/:qID/answers', (req, res, next) => {
req.question.answers.push(req.body);
req.question.save((err, question) => {
if (err) return next(err);
res.status(201);
res.json(question);
});
});
router.put('/:qID/answers/:aID', (req, res, next) => {
req.answer.update(req.body, (err, result) => {
if (err) return next(err);
res.json(result);
});
});
router.delete('/:qID/answers/:aID', (req, res) => {
req.answer.remove(err => {
req.question.save((err, question) => {
if (err) return next(err);
res.json(question);
});
});
});
router.post(
'/:qID/answers/:aID/vote-:dec',
(req, res, next) => {
if (req.params.dec.search(/^(up|down)$/) === -1) {
const err = new Error(`Not possible to vot for ${req.params.dec}!`);
err.status = 404;
next(err);
} else {
req.vote = req.params.dec;
next();
}
},
(req, res, next) => {
req.answer.vote(req.vote, (err, question) => {
if (err) return next(err);
res.json(question);
});
}
);
现在,REST API将开始被使用。现在,REST API已经准备就绪可以被使用了。接下来进入下一个阶段。
清理和测试终端点
API的测试在测试所有的终端点功能时,最简单的方法是使用Postman。您可以使用Chrome扩展或者下载桌面应用程序来实现。无论选择哪个方式都可以,但我个人更喜欢使用Chrome扩展。Postman的使用方法很简单,可以进行HTTP测试。如果您不想手动测试,还可以设置自动化测试。
跨源资源共享出于安全考虑,CORS受到了限制。基本上,它是允许浏览器访问域资源的方法。因此,需要通过以下步骤使用中间件来实现从域中消费API的功能。
跨源资源共享出于安全考虑,CORS受到了限制。基本上,它是允许浏览器访问域资源的方法。因此,需要通过以下步骤使用中间件来实现从域中消费API的功能。
1、所有的来源都需要有访问首部的权限。
2、使HTTP请求有效。
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
if (req.method === 'Options') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, DELETE');
return res.status(200).json({});
}
});
开始前端工作你的API已经配置好,可以与任何类型的前端连接。使用正确的头信息和路径,进行提交、获取、设置和删除操作同样简单。
總結REST API是一种非常好用的工具,可以用于设置可扩展的后端微服务。在这个项目中,我们使用Mongoose在可扩展的开源数据库MongoDB上实现了一个简单的API。让我们尝试使用阿里巴巴云在MongoDB上运行移动应用程序。希望您喜欢这篇文章。
阿里巴巴云已在日本建立了两个数据中心,并拥有超过60个可用区,被誉为2019年亚太地区No.1(根据Gartner)的云基础设施提供商。
欲了解更多阿里巴巴云的详细信息,请点击此处查看阿里巴巴云日本官方页面。