環境建置

Step 1:架設 Express 環境

在 Node.js 下執行以下指令:

  1. npm install express-generator -g
  2. express --view=ejs
  3. npm install
  4. npm start
  5. npm install firebase-admin --save

Add the Firebase Admin SDK to Your Server

完成後開啟 http://localhost:3000/ 查看是否安裝成功,順利的話會出現以下結果:

Express

Step 2:載入 Firestore 到 Node.js

  • 進入 Firebase 的專案設定中產生金鑰

Firebase

  • 下載金鑰後,將金鑰放在根目錄並載入 Node.js
const admin = require('firebase-admin');
let serviceAccount = require('../您的金鑰.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

let db = admin.firestore();

完成以上步驟,金鑰就載入成功囉。

語法說明

Get & Post

  • router.get:取得資料。
  • router.post:使用者新增資料,傳資料到路徑 (form post)。
    例如:送出的位置是 /addStudent (action)。

req

  • req.body:可以抓到使用者從前台傳送過來的數值,通常用 "物件" 的方式傳進來。
    例如:假設 req.body({name: "小明", no: "12"}),那麼 req.body.name 就是 小明 這個值。這個 req.body.namename 就是對應 EJS <input>name 屬性。

常見 res 顯示

  • res.render:顯示網頁 EJS。
    通常用於 Get 取得資料列表後,用 render 渲染該指定頁面的 EJS。
    例如:

    res.render('product', {
      title: '產品列表',
      data: productsData,
    });
  • res.redirect:要 "轉址" 到哪裡。
    例如:透過 Post 傳遞資料後,跳轉至 /students 這個 EJS 頁面。
  • res.send():傳送文字,也可以回傳 JSON 格式,通常是在 "不希望換頁" 的情況下會使用到。
    例如:res.send({"name": "mary"})

範例練習

功能介紹:

  • 顯示 2300 元以下的產品:/products?at=2300
  • 顯示 3 筆資料:/products?limit=3
  • 關鍵字搜尋:/products?keyword=2300
  • 混合使用:/products?keyword=2300&limit=3&at=2300
    (搜尋產品名稱含有 "2300",且價格不高於 2300 元的產品。搜尋結果以價格來做降冪排序,並限制最多只顯示三筆資料)

index.js

var express = require('express');
var router = express.Router();

// 載入 Firestore 到 Node.js
const admin = require('firebase-admin');
let serviceAccount = require('../我的金鑰.json');
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

// 初始化 firebase
let db = admin.firestore();

// 首頁
router.get('/', function(req, res, next) {
  console.log(db); // 檢查有沒有載入成功
  res.render('index', {
    title: 'Express',
  });
});

// 產品頁,網址列可做各種查詢功能
router.get('/products', function(req, res, next) {
  var docRef = db.collection('products2');
  let productsData = [];
  // 價格查詢
  let at = parseInt(req.query.at) || 100000000;
  // 限制數量
  let limit = parseInt(req.query.limit) || 10;

  // 判斷式
  docRef
    .where('price', '<=', at)
    .orderBy('price', 'desc')
    .limit(limit)
    .get()
    .then(function(querySnapshot) {
      querySnapshot.forEach(function(doc) {
        // 關鍵字搜尋
        if (doc.data().name.includes(req.query.keyword)) {
          console.log(doc.data().name, req.query.keyword);
          productsData.push(doc.data());
        }
      });
      res.render('product', {
        title: '產品列表',
        data: productsData,
      });
    });
});

// 新增產品,傳資料到路徑 (表單傳送到後台)
router.post('/addProduct', function(req, res, next) {
  var docRef = db.collection('products2');
  docRef
    .add({
      name: req.body.name,
      price: req.body.price,
    })
    .then(function() {
      res.redirect('/products');
    });
});

// End
module.exports = router;

上面針對不同的查詢功能,都有先宣告一個預設值,這個預設值的用途,是當使用者未使用該項查詢,就帶入預設值做判斷。

例如:以價格查詢功能來說,若使用者並未輸入網址 /products?at= 來做查詢,則會預設帶入 100000000 這個數字做 .where("price", "<=", at) 的判斷並呈現結果。

這邊之所以額外再寫一個 if 做關鍵字的判斷,是因為發現寫兩個 .where() 會導致它出現找不到值的錯誤。

product.ejs

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel="stylesheet" href="/stylesheets/style.css" />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
    <!-- 輸入表單 -->
    <form method="post" action="/addProduct">
      <input name="name" value="" placeholder="輸入產品名稱" />
      <input type="number" name="price" value="" placeholder="輸入價格" />
      <input type="submit" value="送出" />
    </form>
    <!-- 使用 for 迴圈顯示資料庫所有資料 -->
    <% for(let i =0;data.length>i;i++){ %>
    <li><%- data[i].name %> - <%- data[i].price %> 元</li>
    <% } %>
  </body>
</html>

在 EJS 裡面,如果要使用資料,會用到 <%- 資料 -%> 的語法。
而表單的部分也要特別注意,例如:將價格的輸入型別 type 改為 number,以符合資料庫的格式。

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫