在本地开始使用 Firebase Data Connect

在本快速入门中,您将了解如何在本地应用中构建 Firebase Data Connect,而无需设置生产 SQL 实例。您将学习以下内容:

  • Firebase Data Connect 添加到您的 Firebase 项目。
  • 设置一个开发环境,其中包含一个 Visual Studio Code 扩展程序,以便与本地实例搭配使用。
  • 然后,我们将向您展示如何:
    • 为电影应用创建架构
    • 定义将在应用中使用的查询和更改
    • 使用本地模拟器对样本数据测试您的查询和更改
    • 生成强类型 SDK 并在应用中使用它们
    • 将最终架构、查询和数据部署到云端(可选,需要升级到 Blaze 方案)。

选择本地开发流程

Data Connect 提供了两种安装开发工具并在本地工作的方法。

前提条件

如需使用本快速入门,您需要满足以下条件。

  • Firebase 项目。如果您尚未创建项目,请在 Firebase 控制台中创建一个。

设置开发环境

  1. 为您的本地项目创建一个新目录。
  2. 在您创建的新目录中运行以下命令。

      curl -sL https://firebase.tools/dataconnect | bash

    此脚本会尝试为您设置开发环境并启动基于浏览器的 IDE。此 IDE 提供了一些工具(包括预捆绑的 VS Code 扩展程序),可帮助您管理架构,定义要在应用中使用的查询和更改,以及生成强类型 SDK。

alias dataconnect='curl -sL https://firebase.tools/dataconnect | bash'

设置项目目录

如需设置本地项目,请初始化项目目录。在 IDE 窗口的左侧面板中,点击 Firebase 图标以打开 Data Connect VS Code 扩展程序界面:

  1. 点击使用 Google 账号登录按钮。
  2. 点击关联 Firebase 项目按钮,然后在控制台中选择您之前创建的项目。
  3. 点击 Run firebase init 按钮。
  4. 点击启动模拟器按钮。

创建架构

在 Firebase 项目目录的 /dataconnect/schema/schema.gql 文件中,开始定义与电影相关的 GraphQL 架构。

电影

Data Connect 中,GraphQL 字段会映射到列。电影包含 idtitleimageUrlgenreData Connect 可识别基元数据类型:StringUUID

复制以下代码段或取消注释文件中的相应行。

# By default, a UUID id key will be created by default as primary key.
# If you want to specify a primary key, say title, which you can do through
# the @table(key: "title") directive
type Movie @table {
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  imageUrl: String!
  genre: String
}

MovieMetadata

复制以下代码段或取消注释文件中的相应行。

# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # This time, we omit adding a primary key because
  # you can rely on Data Connect to manage it.

  # @unique indicates a 1-1 relationship
  movie: Movie! @unique
  # movieId: UUID <- this is created by the above reference
  rating: Float
  releaseYear: Int
  description: String
}

请注意,movie 字段已映射到 Movie 类型。Data Connect 了解这是 MovieMovieMetadata 之间的关系,并会为您管理这项关系。

在文档中详细了解 Data Connect 架构

向表格添加数据

在 IDE 编辑器面板中,您会在 /dataconnect/schema/schema.gql 中的 GraphQL 类型上方看到 CodeLens 按钮。您可以使用 Add dataRun (Local) 按钮将数据添加到本地数据库。

如需向 MovieMovieMetadata 表添加记录,请执行以下操作:

  1. schema.gql 中,点击 Movie 类型声明上方的添加数据按钮。
    Firebase Data Connect 的 CodeLens“添加数据”按钮
  2. 在生成的 Movie_insert.gql 文件中,为这三个字段硬编码数据。
  3. 点击 Run (Local) 按钮。
    Firebase Data Connect 的 CodeLens 运行按钮
  4. 重复上述步骤,将记录添加到 MovieMetadata 表中,在 movieId 字段中提供电影的 id,如生成的 MovieMetadata_insert 更改中所提示。

如需快速验证是否添加了数据,请执行以下操作:

  1. 返回 schema.gql,点击 Movie 类型声明上方的读取数据按钮。
  2. 在生成的 Movie_read.gql 文件中,点击 Run (Local) 按钮以执行查询。

参阅文档详细了解 Data Connect 更改

定义查询

现在进入有趣的部分:我们来定义应用中需要的查询。 作为开发者,您可能习惯编写 SQL 查询,而不是 GraphQL 查询,因此这在开始时可能会感觉有些不同。

不过,与原始 SQL 相比,GraphQL 要简洁得多,并且具有类型安全性。此外,我们的 VS Code 扩展程序可简化开发体验。

开始修改 /dataconnect/connector/queries.gql 文件。如果您想获取所有电影,请使用如下查询。

# File `/dataconnect/connector/queries.gql`

# @auth() directives control who can call each operation.
# Anyone should be able to list all movies, so the auth level is set to PUBLIC
query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
  }
}

使用附近的 CodeLens 按钮执行查询。

这里有一个非常令人兴奋的功能,就是能够将数据库的关系视为图表。由于 MovieMetadata 记录包含引用电影的 movie 字段,因此您可以嵌套到该字段中,然后返回电影信息。请尝试将生成的类型 movieMetadata_on_movie 添加到 ListMovies 查询。

query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
    movieMetadata_on_movie {
        rating
    }
  }
}

参阅文档,详细了解 Data Connect 查询

生成 SDK 并在应用中使用

在 IDE 的左侧面板中,点击 Firebase 图标以打开 Data Connect VS Code 扩展程序界面:

  1. 点击将 SDK 添加到应用按钮。
  2. 在随即显示的对话框中,选择包含应用代码的目录。Data Connect SDK 代码将生成并保存到该目录中。

  3. 选择您的应用平台,然后请注意,SDK 代码会立即在您选择的目录中生成。

使用 SDK 从应用调用查询

您可以使用 Data Connect 生成的 SDK 实现对 ListMovies 查询的调用。然后,您可以使用 Data Connect 模拟器在本地执行此查询。

Web

  1. 将 Firebase 添加到您的Web 应用。
  2. 在 React 应用的主文件中:

    • 导入生成的 SDK
    • 对应用进行插桩以连接到 Data Connect 模拟器
    • 调用 Data Connect 方法。

    您可以复制以下代码段,并将其作为独立应用运行。

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    
    import { connectDataConnectEmulator } from 'firebase/data-connect';
    
    // Generated queries.
    // Update as needed with the path to your generated SDK.
    import { listMovies, ListMoviesData } from '@movie-app/movies';
    
    const dataConnect = getDataConnect(connectorConfig);
    connectDataConnectEmulator(dataConnect, 'localhost', 9399);
    
    function App() {
      const [movies, setMovies] = useState<ListMoviesData['movies']>([]);
      useEffect(() => {
        listMovies.then(res => setMovies(res.data));
      }, []);
      return (
        movies.map(movie => <h1>{movie.title}</h1>);
      );
    }
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<App />);    
    

Swift

  1. 将 Firebase 添加到您的 iOS 应用。
  2. 如需使用生成的 SDK,请在 Xcode 中将其配置为依赖项。

    在 Xcode 顶部导航栏中,依次选择 File(文件)> Add Package Dependencies(添加软件包依赖项)> Add Local(添加本地内容),然后选择包含生成的 Package.swift 的文件夹。

  3. 在应用的主要委托中:

    • 导入生成的 SDK
    • 对应用进行插桩以连接到 Data Connect 模拟器
    • 调用 Data Connect 方法。

    您可以复制以下代码段,并将其作为独立应用运行。

    import SwiftUI
    
    import FirebaseDataConnect
    // Generated queries.
    // Update as needed with the package name of your generated SDK.
    import <CONNECTOR-PACKAGE-NAME>
    
    let connector = DataConnect.moviesConnector
    
    // Connect to the emulator on "127.0.0.1:9399"
    connector.useEmulator()
    
    // (alternatively) if you're running your emulator on non-default port:
    // connector.useEmulator(port: 9999)
    
    struct ListMovieView: View {
    @StateObject private var queryRef = connector.listMovies.ref()
    
        var body: some View {
            VStack {
                Button {
                    Task {
                        do {
                            try await refresh()
                        } catch {
                            print("Failed to refresh: \(error)")
                        }
                    }
                } label: {
                    Text("Refresh")
                }
    
                // use the query results in a view
                ForEach(queryRef.data?.movies ?? [], id: \.self.id) { movie in
                        Text(movie.title)
                    }
                }
        }
        @MainActor
        func refresh() async throws {
            _ = try await queryRef.execute()
        }
    
        struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ListMovieView()
        }
    }
    

Kotlin Android

  1. 将 Firebase 添加到您的 Android 应用。
  2. 如需使用生成的 SDK,请在 Gradle 中将 Data Connect 配置为依赖项。

    更新 app/build.gradle.kts 中的 pluginsdependencies

    plugins {
      // Use whichever versions of these dependencies suit your application.
      // The versions shown here were the latest as of December 03, 2024.
      // Note, however, that the version of kotlin("plugin.serialization") must,
      // in general, match the version of kotlin("android").
      id("com.android.application") version "8.7.3"
      id("com.google.gms.google-services") version "4.4.2"
      val kotlinVersion = "2.1.0"
      kotlin("android") version kotlinVersion
      kotlin("plugin.serialization") version kotlinVersion
    }
    
    dependencies {
      // Use whichever versions of these dependencies suit your application.
      // The versions shown here were the latest versions as of December 03, 2024.
      implementation("com.google.firebase:firebase-dataconnect:16.0.0-beta03")
      implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
      implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3")
    
      // These dependencies are not strictly required, but will very likely be used
      // when writing modern Android applications.
      implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
      implementation("androidx.appcompat:appcompat:1.7.0")
      implementation("androidx.activity:activity-ktx:1.9.3")
      implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
      implementation("com.google.android.material:material:1.12.0")
    }
    
  3. 在应用的主 activity 中:

    • 导入生成的 SDK
    • 对应用进行插桩以连接到 Data Connect 模拟器
    • 调用 Data Connect 方法。

    您可以复制以下代码段,并将其作为独立应用运行。

    import android.os.Bundle
    import android.widget.TextView
    import androidx.appcompat.app.AppCompatActivity
    import androidx.lifecycle.Lifecycle
    import androidx.lifecycle.lifecycleScope
    import androidx.lifecycle.repeatOnLifecycle
    import kotlinx.coroutines.launch
    
    
    private val connector = com.myapplication.MoviesConnector.instance
      .apply {
        // Connect to the emulator on "10.0.2.2:9399" (default port)
        dataConnect.useEmulator()
    
        // (alternatively) if you're running your emulator on non-default port:
        // dataConnect.useEmulator(port = 9999)
      }
    
    
    class MainActivity : AppCompatActivity() {
    
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView: TextView = findViewById(R.id.text_view)
    
        lifecycleScope.launch {
          lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
            
            val result = connector.listMovies.runCatching { execute { } }
            
            val newTextViewText = result.fold(
              onSuccess = {
                val titles = it.data.movies.map { it.title }
                "${titles.size} movies: " + titles.joinToString(", ")
              },
              onFailure = { "ERROR: ${it.message}" }
            )
            textView.text = newTextViewText
          }
        }
      }
    }
    

Flutter

  1. 将 Firebase 添加到您的 Flutter 应用。
  2. 安装 flutterfire CLI dart pub global activate flutterfire_cli
  3. 运行 flutterfire configure
  4. 在应用的主函数中:

    • 导入生成的 SDK
    • 对应用进行插桩以连接到 Data Connect 模拟器
    • 调用 Data Connect 方法。

    您可以复制以下代码段,并将其作为独立应用运行。

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';

// Generated queries.
// Update as needed with the path to your generated SDK

import 'movies_connector/movies.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  
  MoviesConnector.instance.dataConnect
      .useDataConnectEmulator(Uri.base.host, 443, isSecure: true);
  
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: Column(children: [
      ConstrainedBox(
        constraints: const BoxConstraints(maxHeight: 200),
        child: FutureBuilder(
            future: MoviesConnector.instance.listMovies().execute(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                return ListView.builder(
                  scrollDirection: Axis.vertical,
                  itemBuilder: (context, index) => Card(
                      child: Text(
                    snapshot.data!.data.movies[index].title,
                  )),
                  itemCount: snapshot.data!.data.movies.length,
                );
              }
              return const CircularProgressIndicator();
            }),
      )
    ])));
  }
}

将架构和查询部署到生产环境

在应用中完成本地设置后,您现在可以将架构、数据和查询部署到云端。您需要一个 Blaze 方案项目才能设置 Cloud SQL 实例。

  1. 前往 Firebase 控制台的“Data Connect”部分,然后创建一个免费试用版 Cloud SQL 实例。

  2. 在 IDE 集成的终端中,运行 firebase init dataconnect,然后选择您刚刚在控制台中创建的区域/服务 ID

  3. 当系统提示“File dataconnect/dataconnect.yaml already exists, Overwrite?”时,选择 "Y"

  4. 在 IDE 窗口的 VS Code 扩展程序界面中,点击部署到生产环境按钮。

  5. 部署完成后,请前往 Firebase 控制台,验证架构、操作和数据是否已上传到云端。您应该能够查看架构,并在控制台中运行操作。Cloud SQL for PostgreSQL 实例将更新为最终部署的生成架构和数据。

后续步骤

查看已部署的项目并探索更多工具:

  • Firebase 控制台中向数据库添加数据、检查和修改架构,以及监控 Data Connect 服务。

如需了解详情,请参阅相关文档。例如,既然您已完成快速入门,请执行以下操作: