开发你的第一个数据驱动的Node.js网络应用程序

116 阅读10分钟

开发你的第一个数据驱动的Node.js网络应用程序

你已经创建了你的第一个MongoDB数据库,现在你想在一个网站上使用它。你如何在网络上显示它的数据?用户如何添加、修改和删除数据?解决方案是使用MongoDB节点模块创建一个动态Node.js网络应用。

**注:**第一次开发Node.js网络应用程序或还没有数据库?开始使用Node.js数据库

将MongoDB数据库连接到网络应用程序

首先,我们需要安装MongoDB节点模块,以便将我们在第一部分中创建的本地数据库连接到我们的Web应用。

在终端中,输入。

npm install mongo --save

如果出现added 1 package ,则安装已成功。

其次,我们需要在我们的server.js 文件中添加一些代码,以告诉我们的Express服务器我们的数据库在哪里,以及它需要使用MongoDB节点模块。

在你的server.js 文件的开头添加以下内容。

// Database Connections
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://localhost:27017/firstdb";

url 变量存储了你要使用的数据库的位置。如果你选择了一个不同的数据库名称,请改变firstdb

最后,在你的server.js 文件中的app.use() 之后,我们将创建一个叫做db 的变量,我们将在整个server.js 中使用它来连接我们的数据库。

var db;
// connecting variable db to database
MongoClient.connect(url, function (err, client) {
    if (err) throw err;
    db = client.db('firstdb');
    app.listen(8080);
    console.log('Listening on 8080');
});

同样,如果你的数据库不叫firstdb ,你应该相应地改变它。

到目前为止,你的server.js 文件应该类似于。

// Database Connections
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://localhost:27017/firstdb";

// Node Modules
const express = require('express');
const bodyParser = require('body-parser');
const ejs = require('ejs');
const app = express();

// Initialising Express
app.use(express.static('public'));
// set the view engine to ejs
app.set('view engine', 'ejs');

// connecting variable db to database
var db;
MongoClient.connect(url, function (err, client) {
    if (err) throw err;
    db = client.db('firstdb');
    app.listen(8080);
    console.log('Listening on 8080');
});

// *** GET Routes - display pages ***

// Root Route
app.get('/', function (req, res) {
    res.render('pages/index');
});

创建一个图书数据表

从MongoDB集合中返回数据

由于我们已经有了一个包含数据的数据库,你要学习的第一件事就是如何在网页上显示数据。

假设你按照第一部分的要求,在你的firstdb 数据库中,有一个叫做books 的集合,其中有几个包含namegenre 的条目。我们将把这些数据添加到一个表中,甚至使用CSSTricks中的一些CSS使其变得漂亮。

第一步是添加一个books路由。books路由将包含搜索我们的数据库集合的代码,然后创建一个结果的EJS变量,最后用这个变量渲染一个新页面。

添加以下内容到你的server.js ,在根路由的下面。

// Books Route
app.get('/books', function (req, res) {
    // Find data in books collection
    db.collection('books').find({}).toArray(function (err, result) {
        console.log("Book Collection: " + result);
    // Show books page
        res.render('pages/books');
    });
});

你会注意到db.collection('books').find({}) 与我们在第一部分中在终端做的db.books.find() 命令相似。所有Mongo Shell命令(即终端命令)都可以在Node.js中使用,只是语法有些不同。

.toArray 部分将把结果转换成一个数组,因为会有多个结果。

我们将使用console.log 命令来查看从数据库返回的内容,但首先我们需要为路由添加一个books.ejs 文件。

在你的views/pages 文件夹中,添加books.ejs ,内容如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <%- include('../partials/head') %>
</head>
<body>
    <header>
        <%- include('../partials/header') %>
    </header>
    <main>
        <p>Our Book Database will be displayed here</p>
    </main>
    <footer>
        <%- include('../partials/footer') %>
    </footer>
</body>
</html>

我们只需要在这里添加一些基本的HTML,以便我们可以进行测试。一旦从数据库返回正确的数据,我们就可以把它添加到EJS文件中。

在终端中运行npm start ,然后在浏览器中转到localhost:8080/books

回到你的终端窗口,你应该看到Book Collection: [object Object],[object Object],[object Object],[object Object] ,这并没有什么帮助。

因为它是一个数组(包含多个结果),而不是一个字符串,你必须通过它进行循环 (forEach) 才能看到里面的数据。然而,一个更快速的解决方案是将其转换为字符串,用于记录。

将你的console.log 改为JSON.stringify ,结果如下:console.log("Book Collection:" + JSON.stringify(result)); ,然后重新运行应用程序,再次导航到图书页面。

响应应该包含所有你已经添加到books 集合的数据。

书籍集合console.log 示例

Book Collection:[
    {"_id":"5ed79cc24096aca107f150fc","name":"Harry Potter and the Chamber of Secrets","genre":"Fantasy"},
    {"_id":"5ed7a03df2223b53e6e0defe","name":"Slated","genre":"Sci-Fi"},
    {"_id":"5f269cdeb81a7a48f4618bf3","name":"The Novice","genre":"Fantasy"},
    {"_id":"5f269d45cacefe08bc94bcf1","name":"The Outcast","genre":"Fantasy"}
]

在前端显示数据

恭喜你!你已经成功地从数据库中返回了数据。你已经第一次使用Node.js服务器成功地从MongoDB集合中返回数据。现在,我们只需要在前端显示它。

仍然在server.js ,调整我们的res.render ,将数据库结果作为一个EJS变量传递给前端。

// Show books page
    res.render('pages/books', {
            bookdetails: result
        });

现在在books.ejs ,在<main></main> 标签之间添加以下内容。

<table>
  <% bookdetails.forEach(function(book) { %>
    <th><h3>Name</h3></th>
    <th><h3>Genre</h3></th>
    <tbody>
      <tr>
        <td>
          <p><%= book.name %></p>
        </td>
        <td>
          <p><%= book.genre %></p>
        </td>
      </tr>
    </tbody>
  <% }); %>
</table>

这将创建一个有两个表头的表格:名字和流派。然后对于数组(书籍集合)中的每一个条目,将添加一个新的行,其中有两个单元格。一个是条目的名称,另一个是其流派。

再次运行npm start ,并转到书籍页面。你应该看到这个表和里面的数据。

表格的样式

你已经有了一个包含书籍数据的表格,这很好,但它看起来并不漂亮。幸运的是,CSSTricks为你提供了一些表格的CSS代码片段。

在你的CSS文件中(如果你还没有的话,请在public/css 创建一个),并添加以下内容。

/* Table Styling from CSSTricks*/
table {
    width: 50%;
    margin: 25px auto;
    border-collapse: collapse;
    border: 1px solid #eee;
    border-bottom: 2px solid #ffd633;
    box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1), 0px 10px 20px rgba(0, 0, 0, 0.05), 0px 20px 20px rgba(0, 0, 0, 0.05), 0px 30px 20px rgba(0, 0, 0, 0.05);
}
table tr:hover {
    background: #f4f4f4;
}
table tr:hover td {
    color: #555;
}
table th, table td {
    color: #999;
    border: 1px solid #eee;
    padding: 5px 10px;
    border-collapse: collapse;
}
table th {
    background: #ffd633;
    color: #fff;
    text-transform: uppercase;
    font-size: 14px;
}
table td {
    padding: 15px 10px;
}
table p {
    text-align: center;
}

我通过添加宽度和改变单元格的填充等来调整表格的大小,以适应内容的长度。我还修改了重点颜色以适应该应用程序,所以请随意改变CSS以适应你的风格。

使用npm start 重新加载应用程序,并回到图书页面,表格应该看起来更漂亮了。

从Web应用程序中修改MongoDB集合

目前,我们只使用了在终端中添加到数据库中的数据,但普通用户不应该克隆我们的网络应用程序并建立一个本地数据库来做同样的事情。让我们创建一个表单,用户可以用它来添加、删除或更新我们数据库中的图书条目。

在我们创建一个表单或添加一个路由来添加、删除或修改数据库条目之前,我们需要安装一个节点模块来从提交的表单URL中抓取表单查询。

输入npm install body-parser --save ,然后在我们其他所需的节点模块下面添加const bodyParser = require('body-parser');server.js 。我们还需要在app.use() 之前加入以下内容,以告诉 Express 如何使用body-parser 节点模块。

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

到目前为止,你的server.js 文件应该是这个样子的。

// Database Connections
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://localhost:27017/firstdb";

// Node Modules
const express = require('express');
const bodyParser = require('body-parser');
const ejs = require('ejs');
const app = express();

// Initialising Express
app.use(express.static('public'));
// set the view engine to ejs
app.set('view engine', 'ejs');

// body-parser config
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// connecting variable db to database
var db;
MongoClient.connect(url, function (err, client) {
    if (err) throw err;
    db = client.db('firstdb');
    app.listen(8080);
    console.log('Listening on 8080');
});

// *** GET Routes - display pages ***

// Root Route
app.get('/', function (req, res) {
    res.render('pages/index');
});

// Books Route
app.get('/books', function (req, res) {
    // Find data in books collection
    db.collection('books').find({}).toArray(function (err, result) {
        // Turn array into a JSON string for logging
        console.log("Book Collection: " + JSON.stringify(result));
    // Show books page
    res.render('pages/books', {
            bookdetails: result
        });
    });
});

使用表单将数据添加到MongoDB集合中

为了让用户向我们的数据库集合添加数据,我们首先需要创建一个表单。然后,用户将输入他们想要添加的书的名称和流派,并点击提交按钮。

在你的index.ejs 文件中添加以下HTML。

<form id="addbook" action="/add" method="post">
    <input type="text" id="input-name" name="name" placeholder="Book Title">
    <label for="input-name">Book Name</label>
    <input type="text" id="input-genre" name="genre" placeholder="Book Genre">
    <label for="input-genre">Book Genre</label>
    <button type="submit" value="Add">Add
    </button>
</form>

表单动作指定了提交表单后要做什么。在这种情况下,它将转到我们将继续创建的/add路线。方法被设置为POST,因为/add将是一个POST路由,因为我们要从表单中POST数据。

**注意:**由于可访问性的原因,标签是表单中使用的一个重要标签。他们使用for属性对输入标签进行标注,该属性将自己与相应的输入标签id联系起来。

最后,我们可以创建/add路线。在server.js ,在文件的末尾添加以下内容。

// *** POST Routes ***

// Add Route
app.post('/add', function (req, res) {
    // Get details from the form
    var bookname = req.body.name;
    var bookgenre = req.body.genre;
    // Format book details into JSON
    var bookdetails = { "name": bookname, "genre": bookgenre };
    // Add book details to book collection
    db.collection('books').insertOne(bookdetails, function (err, result) {
        if (err) throw err;
        console.log(result);
        res.redirect('/books');
    });
});

req.body.name and req.body.genre, 从提交的表单URL中抓取name和genre输入的值。然后,bookdetails 变量将数据格式化为JSON,以便MongoDB能够理解它。最后,db.collection('books').insertOne 将我们的bookdetails 条目插入我们的书籍集合,然后将用户重定向到 /books,这样他们就可以看到更新的书籍列表。

运行npm start ,在表格中输入书的名字和它的类型,然后点击添加按钮,就可以自己尝试了。

使用表单从MongoDB集合中删除数据

恭喜你,你已经成功地创建了一个表单,用户可以在其中键入他们的查询;它被添加到本地MongoDB数据库中,一个表被更新为新的信息。

你会发现,创建一个删除数据的表单是一个非常类似的过程。创建一个新表单,但不要有书名和流派的两个输入字段,只需添加一个书名。然后将动作值修改为一个名为/delete的新路径。请看下面的例子。

<form id="deletebook" action="/delete" method="post">
    <input type="text" id="input-name" name="name" placeholder="Book Title">
    <label for="input-name">Book Name</label>
    <button type="submit" value="Delete">
    Delete
    </button>
</form>

server.js ,为/delete添加一个新的路径。

// Delete Route
app.post('/delete', function (req, res) {
    // Get details from the form
    var bookname = req.body.name;
    // Format book details into JSON
    var bookdetails = { "name": bookname };
    // Add book details to book collection
    db.collection('books').deleteOne(bookdetails, function (err, result) {
        if (err) throw err;
        console.log(result);
        res.redirect('/books');
    });
});

正如你所看到的,它几乎与你之前为/add创建的路由相同。唯一的区别是,你要删除一个条目,而不是插入一个,而且你只得到一个输入字段的值。

使用npm start 测试新的表单,以确保它对你有用。

使用表单修改MongoDB集合的数据

我们要创建的最后一个表单(和一块功能)是用来修改数据的。如果你的一个用户犯了一个错,想改正它怎么办?

添加一个有两个输入的新表单,像这样。

<form id="editbook" action="/edit" method="post">
    <input type="text" id="input-editname" name="editname" placeholder="Old Book Name">
    <input type="text" id="input-newname" name="newname" placeholder="New Book Name">
    <button type="submit" value="Edit">
    Edit
    </button>
</form>

最后,在server.js 添加。

// Edit Route
app.post('/edit', function (req, res) {
    // Get details from the form
    var oldbook = req.body.editname;
    var newbook = req.body.newname;
    // Format book details into JSON
    var bookquery = { "name": oldbook };
    var newbookquery = { $set: {name: newbook } };
    // Add book details to book collection
    db.collection('books').updateOne(bookquery, newbookquery, function (err, result) {
        if (err) throw err;
        console.log(result);
        res.redirect('/books');
    });
});

**注意:**更新数据的语法与添加或删除不同。$set 告诉MongoDB应该被更新的查询,updateOne 需要两个变量而不是一个:要更新的旧数据和应该取代它的新数据。

恭喜你,你已经使用Node.js和MongoDB开发了你的第一个数据驱动的网络应用。想进一步开发你的图书数据库,改进设计或查看示例代码?请查看Github Repo。想向用户展示你的第一个数据驱动网络应用吗?了解如何使用DigitalOcean部署一个Node.js网络应用