Firebase Firestore在node.js应用程序中的实现教程

367 阅读6分钟

使用Node.js的Firebase Cloud Firestore

你好。在本教程中,我们将解释Firebase Firestore在node.js应用程序中的实现。该应用程序将负责执行以下操作。

1.1.简介

Firebase是一个BaaS(Backend-as-a-Service),它有助于在数据库中存储实时数据。允许在所有设备上同步实时数据。

特点:

  • 无服务器
  • 高度安全
  • 提供最小的设置
  • 通过Angular Fire提供三方绑定
  • 轻松访问数据、认证和更多
  • 提供JSON存储,意味着数据和对象之间没有障碍
  • 具有良好的存储潜力

就像其他的存储解决方案一样,Firebase也有一些优势,即

  • 对查询和索引的支持有限
  • 不支持聚合和map-reduce功能

1.1 设置Node.js

要在Windows上设置Node.js,你需要从这个链接中下载安装程序。点击你的平台的安装程序(也包括NPM包管理器),运行安装程序,开始Node.js设置向导。按照向导的步骤操作,完成后点击 "完成"。如果一切顺利,你可以导航到命令提示符来验证安装是否成功,如图1所示。

Firebase Firestore in node.js - verifying npm installation

图1: 验证node和npm的安装

2.使用Node.js的Firebase Cloud Firestore

为了设置应用程序,我们将需要导航到我们的项目所在的路径。对于编程的东西,我正在使用Visual Studio Code作为我的首选IDE。你可以自由选择你喜欢的IDE。

2.1 设置Firebase项目

为了设置项目的实施,我们需要一个启用了实时数据库的Firebase项目。一旦项目被创建,就复制Firebase的配置,这将在.env 属性中使用。详情请参考第2.2.2节。你可以看一下这个链接,在google控制台快速创建一个firebase项目。

2.2 设置实现

让我们来写一下实际学习中需要的不同文件。

2.2.1 设置依赖项

导航到项目目录,运行npm init -y ,创建一个package.json 文件。这个文件持有与项目有关的元数据,用于管理项目的依赖关系、脚本、版本等。在该文件中添加以下代码,我们将指定所需的依赖性。

{
  "name": "node-firebase",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "dotenv": "^10.0.0",
    "express": "^4.17.1",
    "firebase": "^8.0.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.15"
  }
}

要下载依赖项,请导航到包含该文件的目录路径,并使用npm install 命令。如果一切顺利,依赖项将被加载到node_modules 文件夹中,你就可以进行下一步了。

2.2.2 创建一个环境文件

在环境文件中添加以下代码。该文件将负责将配置变量分散到整个应用程序中,以便进一步使用。

#express server configuration
PORT=3000
HOST=localhost
HOST_URL=http://localhost:3001

#firebase configuration
API_KEY=your_api_key
AUTH_DOMAIN=app_auth_domain
DATABASE_URL=app_realtime_database_url
PROJECT_ID=app_id
STORAGE_BUCKET=app_storage_bucket
MESSAGING_SENDER_ID=messaging_sender_id
APP_ID=app_id

2.2.3 创建配置文件

将下面的代码添加到配置文件中。该文件将负责从.env 文件中导入环境变量并执行初始化断言。这些断言有助于避免应用程序启动后的常见故障。

const dotenv = require("dotenv");
const assert = require("assert");

dotenv.config();

const {
  PORT,
  HOST,
  HOST_URL,
  API_KEY,
  AUTH_DOMAIN,
  DATABASE_URL,
  PROJECT_ID,
  STORAGE_BUCKET,
  MESSAGING_SENDER_ID,
  APP_ID
} = process.env;

// adding init assertions
assert(PORT, "Application port is required");
assert(HOST_URL, "Service endpoint is required");
assert(DATABASE_URL, "Firebase database endpoint is required");
assert(PROJECT_ID, "Firebase project id is required");
assert(APP_ID, "Firebase app id is required");

module.exports = {
  port: PORT,
  host: HOST,
  url: HOST_URL,
  firebaseConfig: {
    apiKey: API_KEY,
    authDomain: AUTH_DOMAIN,
    databaseURL: DATABASE_URL,
    projectId: PROJECT_ID,
    storageBucket: STORAGE_BUCKET,
    messagingSenderId: MESSAGING_SENDER_ID,
    appId: APP_ID
  }
};

2.2.4 创建数据库配置

在数据库配置文件中加入以下代码。该文件将负责初始化该应用程序所需的Firebase配置。

const firebase = require("firebase");
const config = require("./config");

const db = firebase.initializeApp(config.firebaseConfig);

module.exports = db;

2.2.5 创建一个模型类

在模型类中添加以下代码,该类将负责将数据映射到Firebase Firestore集合中/从该集合中获取数据。

class Employee {
  constructor(id, fullName, age, contact, department) {
    this.id = id; // represents the id generated by the firestore
    this.fullName = fullName;
    this.age = age;
    this.contact = contact;
    this.department = department;
  }
}

module.exports = Employee;

2.2.6 创建一个控制器类

在控制器类中添加以下代码,它将负责从客户端获取数据并与Firebase Firestore集合进行交互。该类由不同的方法组成,用于保存一个新的雇员,更新/删除/通过id获取一个雇员,以及获取所有雇员。

const firebase = require("../db");
const Employee = require("../models/employee");
const fireStore = firebase.firestore();

// performing crud operations in the firebase firestore
// add
// get all
// get
// update
// delete

const addEmployee = async (req, res, next) => {
  try {
    console.log("Adding new employee");
    const data = req.body;
    await fireStore.collection("employees").doc().set(data);
    res.status(201).json({ message: "Record saved successfully" });
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

const getAllEmployees = async (req, res, next) => {
  try {
    console.log("Getting all employees");
    const employees = await fireStore.collection("employees");
    const data = await employees.get();
    const arr = [];
    if (data.empty) {
      res.status(200).json({ message: "No records found" });
    } else {
      let total = 0;
      data.forEach((item) => {
        const employee = new Employee(
          item.id,
          item.data().fullName,
          item.data().age,
          item.data().contact,
          item.data().department
        );
        arr.push(employee);
        total = total + 1;
      });
      res.status(200).json({
        listing: arr,
        count: total
      });
    }
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

const getEmployee = async (req, res, next) => {
  try {
    const id = req.params.id;
    console.log("Getting employee= %s", id);
    const employee = await fireStore.collection("employees").doc(id);
    const data = await employee.get();
    if (!data.exists) {
      res.status(404).json({ message: "Record not found" });
    } else {
      res.status(200).json(data.data());
    }
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

const updateEmployee = async (req, res, next) => {
  try {
    const id = req.params.id;
    console.log("Updating employee= %s", id);
    const data = req.body;
    const employee = await fireStore.collection("employees").doc(id);
    await employee.update(data);
    res.status(204).json({ message: "Record updated successfully" });
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

const deleteEmployee = async (req, res, next) => {
  try {
    const id = req.params.id;
    console.log("Deleting employee= %s", id);
    await fireStore.collection("employees").doc(id).delete();
    res.status(204).json({ message: "Record deleted successfully" });
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

// todo - add delete all employees

module.exports = {
  addEmployee,
  getAllEmployees,
  getEmployee,
  updateEmployee,
  deleteEmployee
};

2.2.7 创建一个路由器类

在路由器类中添加以下代码,它将负责把来自客户端的请求映射到相应的控制器方法中。

const express = require("express");
const {
  addEmployee,
  getAllEmployees,
  getEmployee,
  updateEmployee,
  deleteEmployee
} = require("../controllers/employeeController");

const router = express.Router();

// http://localhost:3000/api/employee
router.post("/employee", addEmployee);

// http://localhost:3000/api/employees
router.get("/employees", getAllEmployees);

// http://localhost:3000/api/employee/xxxx_employee_id
router.get("/employee/:id", getEmployee);

// http://localhost:3000/api/employee/xxxx_employee_id
router.put("/employee/:id", updateEmployee);

// http://localhost:3000/api/employee/xxxx_employee_id
router.delete("/employee/:id", deleteEmployee);

module.exports = {
  routes: router
};

2.2.8 创建一个索引文件

添加以下代码到索引文件中,该文件将负责应用程序的启动并作为应用程序的欢迎点。

const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const config = require("./config");
const employeeRoutes = require("./routes/employeeRoutes");

const app = express();

app.use(express.json());
app.use(cors());
app.use(bodyParser.json());

app.use("/api", employeeRoutes.routes);

app.listen(config.port, () => {
  console.log("Service endpoint= %s", config.url);
});

3.运行应用程序

要运行该应用程序,请导航到项目目录,并输入以下命令,如图2所示。如果一切顺利,应用程序将在从.env 文件中读取的端口号上成功启动。在这种情况下,应用程序将在一个端口号上成功启动 -3001

Fig. 2: 启动应用程序

4.4.演示

你可以自由地使用postman或任何其他你选择的工具来向应用程序的端点发出HTTP请求。

// add an employee
// http post
http://localhost:3000/api/employee

// get all employees
// http get
http://localhost:3000/api/employees

// get an employee
// http get
http://localhost:3000/api/employee/xxxx_employee_id

// update an employee
// http put
http://localhost:3000/api/employee/xxxx_employee_id

// delete an employee
// http delete
http://localhost:3000/api/employee/xxxx_employee_id

这就是本教程的全部内容,我希望这篇文章能为你提供你想要的东西。祝你学习愉快,不要忘记分享!

5.总结

在本教程中,我们学习了如何在nodejs应用程序中集成Firebase。Firebase提供了一个实时数据库,提供了以JSON格式存储的数据,并提供了实现BaaS解决方案的快速方法。你可以从下载部分下载源代码和postman集合。