開始使用 Firebase Data Connect

在本快速入門課程中,您將瞭解如何使用正式版 SQL 執行個體,在應用程式中建構 Firebase Data Connect。您將學會以下內容:

  • Firebase Data Connect 新增至 Firebase 專案。
  • 為應用程式配置 Cloud SQL 執行個體。
  • 設定開發環境,包括 Visual Studio Code 擴充功能,以便與實際工作環境執行個體搭配使用。
  • 接著,我們會說明如何:
    • 為電影應用程式建立結構定義
    • 定義應用程式中要使用的查詢和變異
    • 使用範例資料測試查詢和 mutation
    • 產生強型別 SDK,並在應用程式中使用
    • 將最終結構定義、查詢和資料部署至雲端。

建立 Firebase 專案和 Cloud SQL 資料庫

  1. 如果您尚未建立 Firebase 專案,請先建立。
    1. Firebase 控制台中,按一下「新增專案」,然後按照畫面上的指示操作。
  2. 前往 Firebase 控制台的 Data Connect 專區,然後按照產品設定工作流程操作。
  3. 將專案升級至 Blaze 方案。這樣一來,您就能建立 PostgreSQL 適用的 Cloud SQL 執行個體。

  4. 選取 PostgreSQL 適用的 Cloud SQL 資料庫位置。

  5. 請記下專案、服務和資料庫的名稱和 ID,以便稍後確認。

  6. 按照剩餘的設定流程操作,然後按一下「完成」

選擇開發流程

Data Connect 提供兩種安裝開發工具的方式。

設定開發環境

  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 擴充功能 UI:

  1. 點選「使用 Google 帳戶登入」按鈕。
  2. 按一下「連結 Firebase 專案」按鈕,然後選取先前在控制台中建立的專案。
  3. 按一下「Run firebase init」按鈕,完成流程。
  4. 按一下「Start emulators」按鈕。

建立結構定義

在 Firebase 專案目錄的 /dataconnect/schema/schema.gql 檔案中,開始定義包含電影的 GraphQL 結構定義。

電影

Data Connect 中,GraphQL 欄位會對應至欄。Movie 類型包含 idtitleimageUrlgenreData Connect 會辨識原始資料類型 StringUUID

複製下列程式碼片段,或取消註解檔案中的對應行。

# File `/dataconnect/schema/schema.gql`

# By default, a UUID id key will be created by default as primary key.
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 結構定義

將結構定義部署至實際工作環境

您必須先部署結構定義,才能繼續操作。

在擴充功能 UI 的 Firebase Data Connect 面板下方,按一下「部署至生產環境」

將結構定義部署至實際資料庫後,您應該可以在 Firebase 主控台中查看結構定義。

在表格中新增資料

在 IDE 編輯器面板中,您會看到 CodeLens 按鈕會顯示在 /dataconnect/schema/schema.gql 中的 GraphQL 類型上。由於您已將結構定義部署至正式環境,因此可以使用「Add data」和「Run (Production)」按鈕,將資料新增至後端資料庫。

如要在 Movie 表格中新增記錄,請按照下列步驟操作:

  1. schema.gql 中,按一下 Movie 類型宣告上方的「Add data」按鈕。
    Firebase Data Connect 的 Code Lens「Add data」按鈕
  2. 在產生的 Movie_insert.gql 檔案中,為四個欄位硬式編碼資料。
  3. 按一下「Run (Production)」按鈕。
    Firebase Data Connect 的 Code Lens 執行按鈕
  4. 重複上述步驟,在 MovieMetadata 資料表中新增記錄,並在 movieId 欄位中提供電影的 id,如產生的 MovieMetadata_insert 變異顯示。

如要快速驗證資料是否已新增,請按照下列步驟操作:

  1. 回到 schema.gql,按一下 Movie 型別宣告上方的「Read data」按鈕。
  2. 在產生的 Movie_read.gql 檔案中,按一下「Run (Production)」按鈕執行查詢。

進一步瞭解說明文件中的 Data Connect 變異體

定義查詢

接下來是查詢的部分。開發人員通常會編寫 SQL 查詢,而非 GraphQL 查詢,因此一開始可能會覺得有點不同。不過,GraphQL 比原始 SQL 更精簡,且具有類型安全性。我們的 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 按鈕執行查詢。

進一步瞭解說明文件中的 Data Connect 查詢

產生 SDK

  1. 按一下「Add SDK to app」按鈕。
  2. 在隨即顯示的對話方塊中,選取包含應用程式程式碼的目錄。系統會產生 Data Connect SDK 程式碼並儲存在該目錄中。

  3. 選取應用程式平台後,SDK 程式碼會立即在所選目錄中產生。

將結構定義和查詢部署至實際工作環境

您已完成一個開發迭代作業。您現在可以使用 Firebase 擴充功能 UI 或 Firebase CLI,將結構定義、資料和查詢部署至伺服器,就像為結構定義執行這項操作一樣。

在 IDE 視窗的 VS Code 擴充功能 UI 中,按一下「Deploy to production」按鈕。

部署完成後,請前往 Firebase 控制台,確認結構定義、作業和資料已上傳至雲端。您應該可以查看結構定義,並在控制台中執行作業。系統會更新 PostgreSQL 適用的 Cloud SQL 執行個體,並使用最終部署產生的結構定義和資料。

進一步瞭解如何在說明文件中使用 Data Connect Emulator

使用 SDK 從應用程式呼叫查詢

結構定義和查詢已部署至實際工作環境,您可以使用 Data Connect 產生的 SDK 來實作對 ListMovies 查詢的呼叫。

網頁版

  1. 將 Firebase 新增至網頁應用程式。
  2. 在 React 應用程式的主檔案中:

    • 匯入您產生的 SDK
    • 呼叫 Data Connect 方法。

    您可以複製下列程式碼片段,並將其做為獨立應用程式執行。

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    
    // Generated queries.
    // Update as needed with the path to your generated SDK.
    import { listMovies, ListMoviesData } from '@movie-app/movies';
    
    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 方法。

    您可以複製下列程式碼片段,並將其做為獨立應用程式執行。

    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
    
    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,請將 Data Connect 設為 Gradle 中的依附元件。

    更新 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. 在應用程式的主活動中:

    • 匯入您產生的 SDK
    • 呼叫 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
    
    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 方法。

    您可以複製下列程式碼片段,並將其做為獨立應用程式執行。

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,
  );
  
  
  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();
            }),
      )
    ])));
  }
}

後續步驟

查看已部署的專案,並探索更多工具:

  • Firebase 控制台中,您可以將資料新增至資料庫、檢查及修改結構定義,以及監控 Data Connect 服務。如需更多資訊,請參閱說明文件。舉例來說,您已完成快速入門導覽課程:

  • 進一步瞭解結構定義、查詢和變異式開發

  • 瞭解如何為 webAndroidiOSFlutter 產生用戶端 SDK,以及從用戶端程式碼呼叫查詢和變異。