by Zell Liew

由Zell Liew

使用Express和MongoDB构建CRUD应用程序-第2部分 (Building a CRUD Application with Express and MongoDB — Part 2)

This article is the second part on creating a CRUD application with Express and MongoDB. We’re going to venture deep into the last two operations that were not covered in the first part — UPDATE and DELETE.

本文是使用Express和MongoDB创建CRUD应用程序的第二部分。 我们将深入探讨第一部分中未介绍的最后两个操作-UPDATEDELETE

Without further ado, let’s start the second part.

事不宜迟,让我们开始第二部分。

CRUD —更新 (CRUD — UPDATE)

The UPDATE operation is used when you want to change something. It can only be triggered by browsers through a PUT request. Like the POST request, the PUT request can either be triggered through JavaScript or through a <form>element.

要更改某些内容时,将使用UPDATE操作。 它只能由浏览器通过PUT请求触发。 与POST请求一样, PUT请求可以通过JavaScript或<form>元素触发。

Let’s try triggering a PUT request through JavaScript this time since we’ve already learned how to trigger a request through a <form> element while going through the POST request in the previous article.

让我们尝试通过JavaScript触发PUT请求这个时间,因为我们已经学会了如何当去前作在以前的文章中POST请求通过量^ h触发通过<form>元素的请求。

For the purpose of this tutorial, we’re going to create a button that, when clicked on, will replace the last quote written by Master Yoda with a quote written by Darth Vader.

就本教程而言,我们将创建一个按钮,当单击该按钮时,它将用Darth Vader编写的引用替换Yoda大师写的最后引用。

To do so, we first add a button into the index.ejs file:

为此,我们首先在index.ejs文件中添加一个按钮:

<div>  <h2>Replace last quote written by Master Yoda with a quote written by Darth Vadar</h2>  <button id="update"> Darth Vadar invades! </button></div>

We’re also going to create an external JavaScript file to execute the PUT request when the button is clicked. According to Express conventions, this file is placed in a folder called public

当单击按钮时,我们还将创建一个外部JavaScript文件来执行PUT请求。 根据Express约定,此文件放置在名为public的文件夹中

$ mkdir public$ touch public/main.js

Then, we have to tell Express to make this public folder accessible to the public by using a built-in middleware called express.static

然后,我们必须告诉Express通过使用称为express.static的内置中间件使此公用文件夹可供公众访问

app.use(express.static('public'))

Once this is done, we can add the main.js file to the index.ejs file:

完成此操作后,我们可以将main.js文件添加到index.ejs文件中:

<!-- ... --><script src="main.js"></script></body>

Next, we’re going to send the PUT request when the button is clicked:

接下来,当单击按钮时,我们将发送PUT请求:

// main.jsvar update = document.getElementById('update')
update.addEventListener('click', function () {  // Send PUT Request here})

The easiest way to trigger a PUT request in modern browsers is to use the Fetch API. It is only supported on Firefox, Chrome and Opera, so you might want to use a polyfill if you want to use Fetch on an actual project.

在现代浏览器中触发PUT请求的最简单方法是使用Fetch API 。 它仅在Firefox,Chrome和Opera上受支持,因此,如果要在实际项目上使用Fetch,则可能需要使用polyfill 。

We’re going to send the following fetch request to the server. Have a quick look at it and I’ll explain what it all means:

我们将以下获取请求发送到服务器。 快速浏览一下,我将解释所有含义:

fetch('quotes', {  method: 'put',  headers: {'Content-Type': 'application/json'},  body: JSON.stringify({    'name': 'Darth Vader',    'quote': 'I find your lack of faith disturbing.'  })})

Ready to understand why the Fetch request is written this way? :)

准备了解为何以这种方式编写Fetch请求? :)

Fetch takes in two parameters. The first parameter is a path. In this case, we’re sending the request to /quote, which will be handled on our server.

取入有两个参数。 第一个参数是路径。 在这种情况下,我们会将请求发送到/ quote,它将在我们的服务器上处理。

The second parameter, options, is an optional object that allows you to control a number of different settings. The ones we used above are method, headers and body.

第二个参数options是一个可选对象,允许您控制许多不同的设置。 我们上面使用的是方法,标题和正文。

We set the “method” to “put” because we’re sending a PUT request.

我们将“方法”设置为“放置”,因为我们正在发送PUT请求。

“Headers” here refers to HTTP Headers you want to send to the server. It is an object with multiple key-value pairs.

此处的“标头”是指您要发送到服务器的HTTP标头 。 它是具有多个键值对的对象。

“Body” refers to the content you send to the server.

“正文”是指您发送到服务器的内容。

One thing you may notice is that we’ve set the Content-Type to application/json. We’ve also converted Darth Vader’s quote into JSON in the body with JSON.stringify. We’re making these steps because we’re sending Darth Vadar’s quote in the JSON format (a standard format for sending information on the web) to the server.

您可能会注意到的一件事是,我们已将Content-Type设置为application / json。 我们还使用JSON.stringify将Darth Vader的报价转换为主体中的JSON。 我们之所以要执行这些步骤,是因为我们要以JSON格式(用于在网络上发送信息的标准格式)将Darth Vadar的报价发送到服务器。

Unfortunately, our server doesn’t read JSON data yet. We can teach it to read JSON data by using the bodyparser.json() middleware:

不幸的是,我们的服务器尚未读取JSON数据。 我们可以使用bodyparser.json()中间件来教它读取JSON数据:

app.use(bodyParser.json())

Once we’ve done everything above, we will be able to handle this PUT request by using the put method:

完成上述所有操作后,我们将可以使用put方法处理此PUT请求:

app.put('/quotes', (req, res) => {  // Handle put request })

The next step, then, is to learn how to look for the last quote by Master Yoda and change it to a quote by Darth Vader in MongoDB.

然后,下一步是学习如何查找Yoda大师的最后报价,并将其更改为MongoDB中Darth Vader的报价。

在MongoDB中更新集合 (Updating a Collection in MongoDB)

MongoDB Collections come with a method called findOneAndUpdate that allows us to change one item from the database. It takes in four parameters — query, update, options and a callback.

MongoDB Collections带有一个名为findOneAndUpdate的方法,该方法使我们可以从数据库中更改一项。 它具有四个参数-查询,更新,选项和回调。

db.collections('quotes').findOneAndUpdate(  query,   update,   options,  callback)

The first parameter, query, allows us to filter the collection through key-value pairs given to it. We can filter the quotes collection for Master Yoda’s quotes by setting the name to Yoda.

第一个参数query允许我们通过给定键值对来过滤集合。 我们可以通过将名称设置为Yoda来过滤Yoda大师报价的报价集合。

{  name: 'Yoda'}

The second parameter, update, tells MongoDB what to do with the update request. It uses MongoDB’s update operators like $set, $inc and $push. We will use the $set operator since we’re changing Yoda’s quotes into Darth Vader’s quotes:

第二个参数update告诉MongoDB如何处理更新请求。 它使用MongoDB的更新运算符,例如$ set,$ inc和$ push。 我们将使用$ set运算符,因为我们将Yoda的报价更改为Darth Vader的报价:

{  $set: {    name: req.body.name,    quote: req.body.quote  }}

The third parameter, options, is an optional parameter that allows you to define additional stuff. Since we’re looking for the last quote by Yoda, we will set sort within options to {_id: -1}. This allows MongoDB to search through the database, starting from the newest entry.

第三个参数options是一个可选参数,可用于定义其他内容。 由于我们在寻找Yoda的最后一个报价,因此我们将选项内的sort设置为{_id:-1}。 这允许MongoDB从最新条目开始搜索数据库。

{  sort: {_id:-1}}

There’s a possibility that there aren’t any quotes by Master Yoda in our database. MongoDB does nothing by default when this happens. We can force it to create a new entry if we set the upsert option, which means insert (or save) if no entries are found, to true:

数据库中没有Yoda大师的任何报价。 发生这种情况时,默认情况下,MongoDB不执行任何操作。 如果将upsert选项设置为true,则可以强制它创建一个新条目,这意味着如果没有找到条目,则插入(或保存):

{  sort: {_id: -1},  upsert: true}

The final parameter is a callback function that allows you to do something once MongoDB has replaced the final quote by Yoda with a quote by Darth Vadar. In this case, we can send the results back to the fetch request.

final参数是一个回调函数 ,一旦MongoDB用Darth Vadar的引号替换了Yoda的最终引号,您就可以执行操作。 在这种情况下,我们可以将结果发送回获取请求。

(err, result) => {  if (err) return res.send(err)  res.send(result)}

Here’s the entire findOneAndUpdate command we’ve written over the previous few steps:

这是我们在前几个步骤中编写的整个findOneAndUpdate命令:

app.put('/quotes', (req, res) => {  db.collection('quotes')  .findOneAndUpdate({name: 'Yoda'}, {    $set: {      name: req.body.name,      quote: req.body.quote    }  }, {    sort: {_id: -1},    upsert: true  }, (err, result) => {    if (err) return res.send(err)    res.send(result)  })})

Now, whenever someone clicks on the update button, the browser will send a PUT request through Fetch to our Express server. Then, the server responds by sending the changed quote back to fetch. We can then handle the response within by chaining fetch with a then method. This is possible because Fetch returns a Promise object.

现在,只要有人单击更新按钮,浏览器就会通过Fetch向我们的Express服务器发送一个PUT请求。 然后,服务器通过将更改后的报价发送回获取进行响应。 然后,我们可以通过使用then方法链接提取来处理响应。 这是可能的,因为Fetch返回Promise对象。

The proper way to check if fetch resolved successfully is to use the okmethod on the response object. You can then return res.json() if you want to read the data that was sent from the server:

检查获取是否成功解决的正确方法是在响应对象上使用okmethod。 然后,如果要读取从服务器发送的数据,则可以返回res.json():

fetch({ /* request */ }).then(res => {  if (res.ok) return res.json()}).then(data => {  console.log(data)})

If you are working on a fancy webapp, this is the part where you use JavaScript to update the DOM so users can see the new changes immediately. Updating the DOM is out of the scope of this article, so we’re just going to refresh the browser to see the changes.

如果您使用的是精美的Web应用程序,那么这是您使用JavaScript更新DOM的部分,以便用户可以立即看到新的更改。 更新DOM不在本文的讨论范围之内,因此我们将刷新浏览器以查看更改。

fetch({ /* request */ }).then(res => {  if (res.ok) return res.json()}).then(data => {  console.log(data)  window.location.reload(true)})

That’s it for the CREATE operation! Let’s move on to the final one — DELETE.

CREATE操作就是这样! 让我们继续到最后一个-DELETE

CRUD-删除 (CRUD — DELETE)

The DELETE operation can only be triggered through a DELETE request. It’s similar to the UPDATE request so it’s simple if you understand what we’ve done earlier.

只能通过DELETE请求触发DELETE操作。 它与UPDATE请求类似,因此如果您了解我们之前所做的工作,它很简单。

For this part, let’s learn to delete the first quote by Darth Vader. To do so, we first have to add a button to the index.ejs file.

对于这一部分,让我们学习删除Darth Vader的第一引号。 为此,我们首先必须在index.ejs文件中添加一个按钮。

<div>  <h2>Delete Darth Vader's first quote</h2>  <button id="delete"> Delete first Darth Vader quote </button></div>

Then, we’ll trigger a DELETE request through Fetch whenever the delete button is clicked:

然后,无论何时单击删除按钮,我们都将通过Fetch触发DELETE请求:

var del = document.getElementById('delete')
del.addEventListener('click', function () {  fetch('quotes', {    method: 'delete',    headers: {      'Content-Type': 'application/json'    },    body: JSON.stringify({      'name': 'Darth Vader'    })  })  .then(res => {    if (res.ok) return res.json()  }).  then(data => {    console.log(data)    window.location.reload()  })})

We can then handle the event on our server side with the delete method:

然后,我们可以使用delete方法在服务器端处理事件:

app.delete('/quotes', (req, res) => {  // Handle delete event here})

在MongoDB中删除条目 (Deleting an entry in MongoDB)

MongoDB Collections come with a method called findOneAndDelete that allows us to remove one item from the database. It takes in three parameters — query, options and a callback. These parameters are exactly the same as the ones we used in findOneAndUpdate when updating an entry in MongoDB. The only difference here is that there’s no upsert within options.

MongoDB Collections带有一个名为findOneAndDelete的方法,该方法使我们可以从数据库中删除一项。 它包含三个参数-查询,选项和回调。 这些参数与在MongoDB中更新条目时在findOneAndUpdate中使用的参数完全相同。 唯一的区别是选项中没有upsert。

db.collections('quotes').findOneAndDelete(  query,   options,  callback)

Remember, we are trying to delete the first quote by Darth Vader. To do so, we filter the quotes collection by the name, “Darth Vader”. The query parameter is hence:

请记住,我们正在尝试删除Darth Vader的第一句话。 为此,我们用名称“ Darth Vader”过滤引号集合。 因此,查询参数为:

{  name: req.body.name}

We can skip the options parameter since we don’t have to reverse the sorting order. Then, we can send a response back to the Fetch request in the callback function.

我们可以跳过options参数,因为我们不必颠倒排序顺序。 然后,我们可以在回调函数中将响应发送回Fetch请求。

(err, result) => {  if (err) return res.send(500, err)  res.send('A darth vader quote got deleted')})

The complete code for the delete handler is as follows:

删除处理程序的完整代码如下:

app.delete('/quotes', (req, res) => {  db.collection('quotes').findOneAndDelete({name: req.body.name},   (err, result) => {    if (err) return res.send(500, err)    res.send('A darth vader quote got deleted')  })})

Now, whenever somebody clicks on the delete button, the browser will send a DELETE request through Fetch to our Express server. Then, the server responds by sending either an error or a message back.

现在,只要有人单击删除按钮,浏览器就会通过Fetch向我们的Express服务器发送DELETE请求。 然后,服务器通过发送错误或消息来响应。

As before, we can reload the website when the fetch is successfully completed.

和以前一样,我们可以在成功完成获取后重新加载网站。

fetch({ /* request */ }).then(res => {  if (res.ok) return res.json()}).then(data => {  console.log(data)  window.location.reload(true)})

That’s it for the DELETE operation!

这就是DELETE操作!

结语 (Wrapping Up)

You have now learned all you need to know about creating simple applications with Node and MongoDB. Now, go forth and create more applications, young padawan. May the force be with you.

现在,您已经了解了有关使用Node和MongoDB创建简单应用程序的所有知识。 现在,继续吧,创建更多的应用程序,年轻的padawan。 愿原力与你同在。

翻译自: https://www.freecodecamp.org/news/building-a-crud-application-with-express-and-mongodb-part-2-11d421bb0215/

使用Express和MongoDB构建CRUD应用程序-第2部分相关推荐

  1. 使用Express和MongoDB构建简单的CRUD应用程序

    by Zell Liew 由Zell Liew 使用Express和MongoDB构建简单的CRUD应用程序 (Building a Simple CRUD Application with Expr ...

  2. 使用 Node.js、Express、AngularJS 和 MongoDB 构建一个Web程序

    为什么80%的码农都做不了架构师?>>>    使用 Node.js.Express.AngularJS 和 MongoDB 构建一个实时问卷调查应用程序 2014 年 3 月 20 ...

  3. 使用React,Spring Boot和用户身份验证构建CRUD应用程序

    建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现. 注册 ,再也不会建立auth了! Re ...

  4. 如何使用.NET Core,SQL和HTML和JavaScript构建CRUD应用程序

    目录 介绍 使用代码 下载源代码696.3 KB 介绍 在本文中,我将说明一个端到端解决方案(服务端>后端>前端),以创建新的.NET Core Web服务并在前端使用该服务.我将逐步演示 ...

  5. react和nodejs_如何使用React,TypeScript,NodeJS和MongoDB构建Todo应用

    react和nodejs In this tutorial, we will be using TypeScript on both sides (server and client) to buil ...

  6. angular1.2.27_Angular 8 + Spring Boot 2.2:立即构建一个CRUD应用程序!

    angular1.2.27 "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权 ...

  7. Angular 8 + Spring Boot 2.2:立即构建一个CRUD应用程序!

    "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 如果您已 ...

  8. 在Blazor中构建数据库应用程序——第5部分——查看组件——UI中的CRUD列表操作

    目录 介绍 存储库和数据库 列表功能 基本表单 分页和排序 分页器 分页器数据 分页器控件 排序控件 UIDataTableHeaderColumn 天气预报列表表单 视图 WeatherForeca ...

  9. 在Blazor中构建数据库应用程序——第3部分——UI中的CRUD编辑和查看操作

    目录 介绍 示例项目.代码和链接 基本表单 RecordFormBase EditRecordFormBase 实现表单 WeatherForecastViewerForm WeatherForeca ...

最新文章

  1. Spring Boot中实现跨域的五种方式
  2. iOS - 使用 SQLite 数据库实现数据持久化
  3. 关于数据预处理的一些想法
  4. C++线程同步之事件(生产者与消费者问题)
  5. OpenCV防止数据溢出saturate_cast
  6. Python_模块Module
  7. Python使用pdfkit、wkhtmltopdf将html转换为pdf错误记录文档
  8. 数据库:mysql内置功能-函数
  9. matlab离散信号与系统的时域分析
  10. 谷歌浏览器设置定位_谷歌浏览器手动设置位置信息
  11. C# WinForm开发鼠标连点器
  12. 要管理此计算机上的用户账户,Win10安装软件用户账户控制提示管理员已阻止运行此应用解决方法...
  13. c语言中eof的作用,C语言中,怎么用EOF结束输入?
  14. 【Python数据分析之pandas01】两个常用的数据结构
  15. “数据源“SqlServer ”包含无法用于处理操作的 ImpersonationMode。不能与名称为“SqlServer ”的数据源进行连接。”
  16. Html id 选择器
  17. mac重装系统 未能与恢复服务器,Mac系统重装后数据可不可以恢复
  18. 拼多多item_get_app - 根据ID取商品详情原数据
  19. StringBoot(模板 Thymeleaf 高阶用法)
  20. 手把手教学训练MTCNN模型.

热门文章

  1. 演练 打印直角三角形
  2. python-函数的定义与调用
  3. jquery-获取表格最后一行的序号
  4. javascript-变量的命名-数据类型-注释
  5. javascript函数节流、防抖及使用场景
  6. 超简单利用xposed框架破解钉钉打卡
  7. (一)Rational Rose 2007 下载安装
  8. 关于Java的反射机制,你需要理解这些...
  9. 网络电话全民亲情祝福 中秋团圆新方式
  10. 重复包含定义 导致未定义类型不识别错误