播种数据并执行批量数据操作

Firebase Data Connect 中,使用更改执行批量数据操作。即使您的 Data Connect 项目在 PostgreSQL 中存储数据,您也无法使用 SQL 语句或 SQL 工具批量加载数据:您的 Data Connect 服务及其架构必须与数据库保持同步,直接在 PostgreSQL 中操作会破坏这种同步。

Data Connect 中,您可以使用更改来种子数据和管理批量数据。您可以通过不同的方式创建和调用数据管理更改,具体取决于您的工作流和环境:

  • 本地开发环境中,在构建应用原型时,您可以使用 VS Code 扩展程序、Data Connect 模拟器和本地数据库实例在本地开发环境中创建和调用数据种子更改。

  • 生产开发阶段,执行更大的 CI/CD 流程并管理生产数据时,您可以使用 Firebase Admin SDK,这组库在特权环境中运行。

本地开发:在本地实例中播种数据

入门指南中,您设置了一个应用,以使用临时插入更改将一条记录添加到单个表中。

为了能够使用,电影评价应用需要电影、评价和用户的数据,以便对包含真实数据的多个表使用联接和其他操作来对查询和更改进行原型设计。您可以扩展架构并为数据库添加种子数据。

您的原型设计环境需要代码来执行数据种子。本指南提供了一些示例,说明了以下内容:

  • 对各个表使用 _insertMany_upsertMany
  • 对相关表使用 _insertMany

更新电影评价应用架构

您可以使用 _insertMany_upsertMany 更新操作一次更新一个数据库表,也可以更新通过联接关系关联的多个表。下方显示了展开的电影评价应用架构,有助于说明这些用例和示例。它将 schema.gql 扩展到了起始 Movie 类型之外,还包括 ActorMovieActor 类型,以便我们对更复杂的查询进行原型设计。

# Actors
# Suppose an actor can participate in multiple movies and movies can have multiple actors
# Movie - Actors (or vice versa) is a many to many relationship
type Actor @table {
  id: UUID!
  imageUrl: String! 
  name: String! @col(name: "name", dataType: "varchar(30)")
}

# Join table for many-to-many relationship for movies and actors
# The 'key' param signifies the primary key(s) of this table
# In this case, the keys are [movieId, actorId], the generated fields of the reference types [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
  # @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type
  # In this case, @ref(fields: "movieId", references: "id") is implied
  movie: Movie!
  # movieId: UUID! <- this is created by the implied @ref
  actor: Actor!
  # actorId: UUID! <- this is created by the implied @ref
  role: String! # "main" or "supporting"
}

写入变更以初始化零状态数据

在原型设计期间,如果需要针对一系列离散值测试查询和更改,您可以使用多个记录填充数据。例如,您可能需要添加多个电影记录,这些记录具有不同类型的分类和评分,以便测试比较和过滤功能。

将种子数据插入 MovieActor

根据您当前的原型设计阶段,您可以使用“开始使用”指南中介绍的相同方法插入一项或两项记录:也就是说,您可以使用 VS Code 扩展程序中的 CodeLenses 创建 _insert 更改、硬编码数据,并在 VS Code 中运行这些更改

最终,使用 _insertMany 操作将多个记录添加到表中更为合理。在电影评论应用示例中,这会在 MovieActor 中插入一组初始数据。

如需执行以下更改,请使用 VS Code Firebase 扩展程序,在相应的文件编辑器视图中,点击 Run (Production)Run (Local) CodeLens 按钮,具体取决于您是使用生产服务还是本地数据库进行原型设计。

# insertMany for Movie
# 2 records shown
mutation {
  movie_insertMany(data: [
    {
      id: "550e8400-e29b-41d4-a716-446655440000",
      title: "Inception",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Finception.jpg?alt=media&token=07b09781-b302-4623-a5c3-1956d0143168",
      genre: "sci-fi",
    },
    {
      id: "550e8400-e29b-41d4-a716-446655440001",
      title: "The Matrix",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Fthe_matrix.jpg?alt=media&token=4975645d-fef8-409e-84a5-bcc1046e2059",
      genre: "action",
    }
  ])
}
# insertMany for Actor
# 2 records shown
mutation {
  actor_insertMany(data: [
    {
      id: "123e4567-e89b-12d3-a456-426614174000",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/actors%2Fdicaprio.jpeg?alt=media&token=452e030a-efa5-4ef4-bb81-502b23241316",
      name: "Leonardo DiCaprio"
    },
    {
      id: "123e4567-e89b-12d3-a456-426614174001",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/actors%2Fkeanu.jpg?alt=media&token=6056520c-ef3e-4823-aad0-108aab163115",
      name: "Keanu Reeves"
    }
   ])
}

将数据作为种子数据插入 MovieActor 联接表

如需使用联接和其他复杂操作测试查询和更改,您可以向 MovieActor 表添加多个记录。

在这里,如果您要更新此类关系中的多个表,可以添加 @transaction 指令,以确保更新正常完成。

mutation @transaction {
  movie_insertMany(data: [
    {
      id: "550e8400-e29b-41d4-a716-446655440000",
      title: "Inception",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Finception.jpg?alt=media&token=07b09781-b302-4623-a5c3-1956d0143168",
      genre: "sci-fi",
    },
    {
      id: "550e8400-e29b-41d4-a716-446655440001",
      title: "The Matrix",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Fthe_matrix.jpg?alt=media&token=4975645d-fef8-409e-84a5-bcc1046e2059",
      genre: "action",
    }
  ])

  actor_insertMany(data: [
    {
      id: "123e4567-e89b-12d3-a456-426614174000",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/actors%2Fdicaprio.jpeg?alt=media&token=452e030a-efa5-4ef4-bb81-502b23241316",
      name: "Leonardo DiCaprio"
    },
    {
      id: "123e4567-e89b-12d3-a456-426614174001",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/actors%2Fkeanu.jpg?alt=media&token=6056520c-ef3e-4823-aad0-108aab163115",
      name: "Keanu Reeves"
    }
  ])
}

编写用于重置种子数据的更改

在进行原型设计和执行 CI/CD 时,将数据重置为零状态,以便对新的数据集执行一系列新测试,这可能会很有用。

为此,如果您的原型代码未向表中添加记录,请使用 Data Connect 提供的 _upsertMany 更改。

在以下示例中,使用初始值调用 movie_upsertMany 以将电影记录更新为原始状态。

mutation {
  # Execute an upsertMany operation to update the Movie table
  movie_upsertMany(data: [
    {
      id: "550e8400-e29b-41d4-a716-446655440000",
      title: "Inception",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Finception.jpg?alt=media&token=07b09781-b302-4623-a5c3-1956d0143168",
      genre: "sci-fi",
    },
    {
      id: "550e8400-e29b-41d4-a716-446655440001",
      title: "The Matrix",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Fthe_matrix.jpg?alt=media&token=4975645d-fef8-409e-84a5-bcc1046e2059",
      genre: "action",
    }
   
}

生产开发:使用 Admin SDK 进行填充和更新

当您想在特权环境中工作时,可以使用 Firebase Admin SDK。由于对生产数据执行批量数据操作具有重要性,因此当您想要加载数千条记录时,这是一个重要的用例。

安装 Firebase Admin SDK

即使您主要在本地工作,Firebase 也建议您设置 Admin SDK,以便您从特权环境(包括本地环境)使用 Firebase Data Connect。您需要为 Node.js 设置 Admin SDK

您可以详细了解如何在其他 Data Connect 用例中使用 Admin SDK

对生产数据执行批量加载和更新

用于批量数据管理的 API 会代表您构建 GraphQL 更改,而不是要求您使用前面介绍的 executeGraphQL API 构建 mutation {...} 字符串,以便在本地添加一些行。

管理 API 的一个主要优势是,能够单独管理和重复使用 CI/CD 流水线的数据数组,或为生产数据设置大型批量数据文件。

以下代码段演示了如何设置批量数据脚本。

import { initializeApp } from 'firebase-admin/app';
import { getDataConnect } from 'firebase-admin/data-connect';

const app = initializeApp();

const dc = getDataConnect({ ___location: "us-west2", serviceId: "my-service" });

const data = [
 {
      id: "550e8400-e29b-41d4-a716-446655440000",
      title: "Inception",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Finception.jpg?alt=media&token=07b09781-b302-4623-a5c3-1956d0143168",
      genre: "sci-fi",
  },
  {
      id: "550e8400-e29b-41d4-a716-446655440001",
      title: "The Matrix",
      imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-quickstart-web.appspot.com/o/movies%2Fthe_matrix.jpg?alt=media&token=4975645d-fef8-409e-84a5-bcc1046e2059",
      genre: "action",
    }
];

// Methods of the bulk operations API
const resp = await dc.insert("movie" /*table name*/, data[0]);
// Or
const resp = await dc.insertMany("movie" /*table name*/, data);

// Or
const resp = await dc.upsert("movie" /*table name*/, data[0]);
// Or
const resp = await dc.upsertMany("movie" /*table name*/, data);

后续步骤