GSP642


總覽
莉莉在十二年前創立了連鎖獸醫診所 Pet Theory。過去幾年來,Pet Theory 的連鎖事業成長得非常快速。不過,由於舊有的預約系統無法因應增加的顧客需求,因此莉莉請您幫忙建構比舊版解決方案更容易擴充的雲端式系統。
Pet Theory 的營運團隊只有阿克一個人,因此需要不必持續頻繁維護的解決方案。阿克決定採用無伺服器技術。
他聘請小茹擔任顧問,協助 Pet Theory 改採無伺服器設計。比較幾個無伺服器資料庫方案後,阿克決定選擇 Cloud Firestore。由於 Firestore 採無伺服器設計,所以不必提前佈建容量,亦即沒有儲存空間或作業限制的風險。Firestore 會透過即時事件監聽器,在用戶端應用程式間同步處理資料,並支援離線使用行動版和網頁版,因此只要應用程式能夠回應,就能建構相關工作,不受網路延遲或連線問題影響。
在本實驗室中,您將協助阿克,將 Pet Theory 的現有資料上傳到 Cloud Firestore 資料庫;而他會與小茹密切合作來完成此工作。
架構
下方圖表概述了您將使用的服務,以及這些服務之間的關係:

目標
本實驗室的學習內容包括:
- 在 Google Cloud 中設定 Firestore。
- 編寫資料庫匯入程式碼。
- 產生一組顧客資料用於測試。
- 將測試的顧客資料匯入 Firestore。
先備知識
這是入門等級的實驗室,亦即假設您已熟悉 Cloud 控制台和殼層環境。具備 Firebase 的使用經驗會有所幫助,但沒有也無妨。
此外,您也須熟悉檔案的編輯方式。您可以使用慣用的文字編輯器 (例如 nano
、vi
等),或是從 Cloud Shell 頂端的工具列啟動程式碼編輯器:

準備好後,請向下捲動,並按照下列步驟設定實驗室環境。
設定和需求
點選「Start Lab」按鈕前的須知事項
請詳閱以下操作說明。研究室活動會計時,而且中途無法暫停。點選「Start Lab」 後就會開始計時,讓您瞭解有多少時間可以使用 Google Cloud 資源。
您將在真正的雲端環境中完成實作研究室活動,而不是在模擬或示範環境。為達此目的,我們會提供新的暫時憑證,讓您用來在研究室活動期間登入及存取 Google Cloud。
如要完成這個研究室活動,請先確認:
- 您可以使用標準的網際網路瀏覽器 (Chrome 瀏覽器為佳)。
注意:請使用無痕模式或私密瀏覽視窗執行此研究室。這可以防止個人帳戶和學生帳戶之間的衝突,避免個人帳戶產生額外費用。
- 是時候完成研究室活動了!別忘了,活動一開始將無法暫停。
注意:如果您擁有個人 Google Cloud 帳戶或專案,請勿用於本研究室,以免產生額外費用。
如何開始研究室及登入 Google Cloud 控制台
-
按一下「Start Lab」(開始研究室) 按鈕。如果研究室會產生費用,畫面中會出現選擇付款方式的彈出式視窗。左側的「Lab Details」窗格會顯示下列項目:
- 「Open Google Cloud console」按鈕
- 剩餘時間
- 必須在這個研究室中使用的暫時憑證
- 完成這個實驗室所需的其他資訊 (如有)
-
點選「Open Google Cloud console」;如果使用 Chrome 瀏覽器,也能按一下滑鼠右鍵,然後選取「在無痕式視窗中開啟連結」。
接著,實驗室會啟動相關資源並開啟另一個分頁,當中顯示「登入」頁面。
提示:您可以在不同的視窗中並排開啟分頁。
注意:如果頁面中顯示「選擇帳戶」對話方塊,請點選「使用其他帳戶」。
-
如有必要,請將下方的 Username 貼到「登入」對話方塊。
{{{user_0.username | "Username"}}}
您也可以在「Lab Details」窗格找到 Username。
-
點選「下一步」。
-
複製下方的 Password,並貼到「歡迎使用」對話方塊。
{{{user_0.password | "Password"}}}
您也可以在「Lab Details」窗格找到 Password。
-
點選「下一步」。
重要事項:請務必使用實驗室提供的憑證,而非自己的 Google Cloud 帳戶憑證。
注意:如果使用自己的 Google Cloud 帳戶來進行這個實驗室,可能會產生額外費用。
-
按過後續的所有頁面:
- 接受條款及細則。
- 由於這是臨時帳戶,請勿新增救援選項或雙重驗證機制。
- 請勿申請免費試用。
Google Cloud 控制台稍後會在這個分頁開啟。
注意:如要查看列出 Google Cloud 產品和服務的選單,請點選左上角的「導覽選單」。
啟動 Cloud Shell
Cloud Shell 是搭載多項開發工具的虛擬機器,提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作。Cloud Shell 提供指令列存取權,方便您使用 Google Cloud 資源。
- 點按 Google Cloud 控制台上方的「啟用 Cloud Shell」圖示
。
連線完成即代表已通過驗證,且專案已設為您的 PROJECT_ID。輸出內容中有一行宣告本工作階段 PROJECT_ID 的文字:
您在本工作階段中的 Cloud Platform 專案會設為「YOUR_PROJECT_ID」
gcloud
是 Google Cloud 的指令列工具,已預先安裝於 Cloud Shell,並支援 Tab 鍵自動完成功能。
- (選用) 您可以執行下列指令來列出使用中的帳戶:
gcloud auth list
-
點按「授權」。
-
輸出畫面應如下所示:
輸出內容:
ACTIVE: *
ACCOUNT: student-01-xxxxxxxxxxxx@qwiklabs.net
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- (選用) 您可以使用下列指令來列出專案 ID:
gcloud config list project
輸出內容:
[core]
project = <project_ID>
輸出內容範例:
[core]
project = qwiklabs-gcp-44776a13dea667a6
附註:如需有關 gcloud
的完整說明,請前往 Google Cloud 並參閱「gcloud CLI overview guide」(gcloud CLI 總覽指南)。
工作 1:在 Google Cloud 中設定 Firestore
阿克的工作是將 Pet Theory 的現有資料上傳到 Cloud Firestore 資料庫;他會與小茹密切合作來完成此目標。小茹收到來自阿克 IT 部門的訊息...

IT 管理員阿克
|
小茹你好:
採用無伺服器技術的第一步,是要使用 Google Cloud 建立 Firestore 資料庫。你能協助我順利完成這項工作嗎?我對這方面的設定不是很熟悉。
阿克
|

軟體顧問小茹
|
阿克你好:
沒問題,我很樂意幫忙。我會寄給你一些新手入門資源,你成功建立資料庫後,我們再聯絡。
小茹
|
請協助阿克使用 Cloud 控制台設定 Firestore 資料庫。
-
在 Cloud 控制台中點選「導覽選單」,然後選取「Firestore」。
-
按一下「+建立資料庫」。
-
選取「原生模式」選項,然後點選「繼續」。
注意:這兩種模式在同步一致性方面的成效都很好,但兩者看起來有差別,且經最佳化的用途也不同。
-
「原生模式」適用於讓多位使用者同時存取同一資料;此外,其中也有即時更新等功能,甚至可在資料庫和網頁/行動用戶端間直接連線。
- 「資料庫模式」的重點在於高處理量 (能因應大量讀寫作業)。
- 在「區域」下拉式選單中,選取 區域,然後點選「建立資料庫」。
這項工作完成後,小茹寄出電子郵件給阿克...

軟體顧問小茹
|
阿克你好:
你設定 Firestore 資料庫了,做得好!為管理資料庫存取權,我們會用到系統自動建立的服務帳戶,內有必要權限。
現在可以從舊資料庫遷移到 Firestore 了!
小茹
|

IT 管理員阿克
|
小茹妳好:
感謝你幫忙,Firestore 資料庫設定起來並不難。
希望這次的資料庫匯入程序會比舊有資料庫簡單,當時程序蠻複雜的,需要很多步驟。
阿克
|
工作 2:編寫資料庫匯入程式碼
新的 Cloud Firestore 資料庫已設定完成,但其中沒有資料。Pet Theory 的顧客資料仍只存放在舊資料庫中。
阿克傳了訊息給小茹...

IT 管理員阿克
|
小茹你好:
經理想要開始將顧客資料遷移到新的 Firestore 資料庫了。
我已從舊資料庫匯出 CSV 檔案,但不太知道怎麼將這份資料匯入 Firestore。
你可以幫幫我嗎?
阿克
|

軟體顧問小茹
|
阿克你好:
沒問題,我們開個會,討論需要做些什麼吧!
小茹
|
就像阿克所說,系統是以 CSV 檔案格式提供顧客資料。現在我們要幫他建立一款應用程式,用來讀取 CSV 檔案中的顧客記錄,然後寫入 Firestore 中。由於阿克慣用 JavaScript,我們將透過 Node.js JavaScript 執行階段建構這款應用程式。
- 在 Cloud Shell 中執行以下指令,複製 Pet Theory 存放區:
git clone https://github.com/rosera/pet-theory
- 使用 Cloud Shell 程式碼編輯器 (或您慣用的編輯器) 編輯檔案。請在 Cloud Shell 工作階段中,按一下頂端工具列的「開啟編輯器」,系統會開啟新分頁。如果出現提示訊息,請點選「在新視窗中開啟」,藉此啟動程式碼編輯器:

- 接著,將目前的工作目錄改為
lab01
:
cd pet-theory/lab01
在目錄中,您會看到阿克的 package.json
。這份檔案列有 Node.js 專案需用到的套件,可讓您重現版本,因此與人共用時會更輕鬆。
以下是 package.json
檔案範例:
{
"name": "lab01",
"version": "1.0.0",
"description": "This is lab01 of the Pet Theory labs",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Patrick - IT",
"license": "MIT",
"dependencies": {
"csv-parse": "^5.5.3"
}
}
阿克現在匯入原始碼了,所以他聯繫小茹,詢問需要哪些套件才能使遷移工作順利進行。

IT 管理員阿克
|
小茹你好:
我在舊資料庫使用的程式碼很基本,只建立了用於匯入程序的 CSV。在開始遷移前,還需要下載什麼嗎?
阿克
|

軟體顧問小茹
|
阿克你好:
有很多 @google-cloud Node.js 套件可與 Firestore 搭配使用,建議你選用一款。
這樣一來,我們應該就只需要稍微修改一下現有程式碼,因為繁重的工作已由套件負責。
小茹
|
為了讓阿克的程式碼順利寫入 Firestore 資料庫中,您需要額外安裝幾個同類依附元件。
- 執行下列指令來進行這項操作:
npm install @google-cloud/firestore
- 安裝附加模組,讓應用程式將記錄檔寫入 Cloud Logging 中:
npm install @google-cloud/logging
成功完成指令後,package.json
會自動更新,納入新的同類依附元件,像下面這樣:
...
"dependencies": {
"@google-cloud/firestore": "^7.3.0",
"@google-cloud/logging": "^11.0.0",
"csv-parse": "^5.5.3"
}
現在來看看指令碼如何讀取顧客的 CSV 檔案,然後將其中各行逐一寫入 Firestore 記錄中。下面是阿克原本的應用程式:
const csv = require('csv-parse');
const fs = require('fs');
function writeToDatabase(records) {
records.forEach((record, i) => {
console.log(`ID: ${record.id} Email: ${record.email} Name: ${record.name} Phone: ${record.phone}`);
});
return ;
}
async function importCsv(csvFilename) {
const parser = csv.parse({ columns: true, delimiter: ',' }, async function (err, records) {
if (e) {
console.error('Error parsing CSV:', e);
return;
}
try {
console.log(`Call write to Firestore`);
await writeToDatabase(records);
console.log(`Wrote ${records.length} records`);
} catch (e) {
console.error(e);
process.exit(1);
}
});
await fs.createReadStream(csvFilename).pipe(parser);
}
if (process.argv.length < 3) {
console.error('Please include a path to a csv file');
process.exit(1);
}
importCsv(process.argv[2]).catch(e => console.error(e));
指令碼會從輸入內容 CSV 檔案中擷取輸出內容,然後匯入到舊資料庫中。接著,我們來更新這組程式碼,寫入到 Firestore 中。
- 開啟
pet-theory/lab01/importTestData.js
檔案。
如要透過應用程式參照 Firestore API,您需要將同類依附元件新增到現有程式碼集中。
- 在檔案第 3 行處加入以下 Firestore 依附元件:
const { Firestore } = require("@google-cloud/firestore");
確保檔案頂端內容如下所示:
const csv = require('csv-parse');
const fs = require('fs');
const { Firestore } = require("@google-cloud/firestore"); // Add this
與 Firestore 資料庫的整合作業可透過幾行程式碼達成。為此,小茹提供了一些範本程式碼給您和阿克參考。
- 請將以下程式碼加到第 34 行下方,或
if (process.argv.length < 3)
條件式之後:
async function writeToFirestore(records) {
const db = new Firestore({
// projectId: projectId
});
const batch = db.batch()
records.forEach((record)=>{
console.log(`Write: ${record}`)
const docRef = db.collection("customers").doc(record.email);
batch.set(docRef, record, { merge: true })
})
batch.commit()
.then(() => {
console.log('Batch executed')
})
.catch(err => {
console.log(`Batch error: ${err}`)
})
return
}
上方程式碼片段宣告了新的資料庫物件,後者會參照稍早在實驗室中建立的資料庫。函式則採用批次處理程序,亦即每筆記錄會依序處理,並根據新增的 ID 產出文件參照。在函式結尾,批次內容會修訂 (寫入) 到資料庫中。
- 更新
importCsv
函式,將函式呼叫新增到 writeToFirestore 中,並移除對 writeToDatabase 的呼叫,如下所示:
async function importCsv(csvFilename) {
const parser = csv.parse({ columns: true, delimiter: ',' }, async function (err, records) {
if (err) {
console.error('Error parsing CSV:', err);
return;
}
try {
console.log(`Call write to Firestore`);
await writeToFirestore(records);
// await writeToDatabase(records);
console.log(`Wrote ${records.length} records`);
} catch (e) {
console.error(e);
process.exit(1);
}
});
await fs.createReadStream(csvFilename).pipe(parser);
}
- 為應用程式新增記錄。如要透過應用程式參照 Logging API,請將同類依附元件新增到現有程式碼集中。在檔案頂端的其他 require 陳述式正下方,新增下面這行:
const { Logging } = require('@google-cloud/logging');
確保檔案頂端內容如下所示:
const csv = require('csv-parse');
const fs = require('fs');
const { Firestore } = require("@google-cloud/firestore");
const { Logging } = require('@google-cloud/logging');
- 新增幾個常數變數,然後將 Logging 用戶端初始化。請將這些變數加到檔案中,位置在上例那行的正下方 (約第 5 行處),如下所示:
const logName = "pet-theory-logs-importTestData";
// Creates a Logging client
const logging = new Logging();
const log = logging.log(logName);
const resource = {
type: "global",
};
- 新增程式碼,在 "console.log(
Wrote ${records.length} records
);" 這行正下方,將記錄寫入 importCsv
函式中,看起來應會像這樣:
// A text log entry
success_message = `Success: importTestData - Wrote ${records.length} records`;
const entry = log.entry(
{ resource: resource },
{ message: `${success_message}` }
);
log.write([entry]);
完成這些更新後,importCsv
函式的程式碼區塊應如下所示:
async function importCsv(csvFilename) {
const parser = csv.parse({ columns: true, delimiter: ',' }, async function (err, records) {
if (err) {
console.error('Error parsing CSV:', err);
return;
}
try {
console.log(`Call write to Firestore`);
await writeToFirestore(records);
// await writeToDatabase(records);
console.log(`Wrote ${records.length} records`);
// A text log entry
success_message = `Success: importTestData - Wrote ${records.length} records`;
const entry = log.entry(
{ resource: resource },
{ message: `${success_message}` }
);
log.write([entry]);
} catch (e) {
console.error(e);
process.exit(1);
}
});
await fs.createReadStream(csvFilename).pipe(parser);
}
現在當應用程式程式碼執行時,Firestore 資料庫就會更新為 CSV 檔案的內容。函式 importCsv
將擷取檔案名稱並逐行剖析內容,所處理的各行現在都會傳送到 Firestore 函式 writeToFirestore
,而每筆新記錄則寫入到「customer」資料庫中。
注意:在正式環境中,您將寫入自己的匯入指令碼版本。
工作 3:建立測試資料
現在可以匯入一些資料了!阿克聯絡小茹,提到他對使用實際顧客資料執行測試有顧慮...

IT 管理員阿克
|
小茹你好:
我覺得不要將顧客資料用於測試會比較好。我們需要讓顧客保有隱私,同時也要確保資料匯入指令碼能正確運作。
你能想出別種測試方式嗎?
阿克
|

軟體顧問小茹
|
阿克你好:
你說得對!這個區塊很棘手,因為顧客資料可能含有個人識別資訊,也就是 PII。
我會提供一些用於建立偽顧客資料的範例程式碼給你。這樣我們就能使用這項資料來測試匯入指令碼。
小茹
|
請協助阿克完成設定,讓這個偽隨機資料產生器順利運作。
- 首先,安裝「faker」資料庫,供生成偽顧客資料的指令碼使用。請執行下列指令,更新
package.json
中的依附元件:
npm install faker@5.5.3
- 現在使用程式碼編輯器開啟名為 createTestData.js 的檔案,然後檢查程式碼,確認是否像下面這樣:
const fs = require('fs');
const faker = require('faker');
function getRandomCustomerEmail(firstName, lastName) {
const provider = faker.internet.domainName();
const email = faker.internet.email(firstName, lastName, provider);
return email.toLowerCase();
}
async function createTestData(recordCount) {
const fileName = `customers_${recordCount}.csv`;
var f = fs.createWriteStream(fileName);
f.write('id,name,email,phone\n')
for (let i=0; i<recordCount; i++) {
const id = faker.datatype.number();
const firstName = faker.name.firstName();
const lastName = faker.name.lastName();
const name = `${firstName} ${lastName}`;
const email = getRandomCustomerEmail(firstName, lastName);
const phone = faker.phone.phoneNumber();
f.write(`${id},${name},${email},${phone}\n`);
}
console.log(`Created file ${fileName} containing ${recordCount} records.`);
}
recordCount = parseInt(process.argv[2]);
if (process.argv.length != 3 || recordCount < 1 || isNaN(recordCount)) {
console.error('Include the number of test data records to create. Example:');
console.error(' node createTestData.js 100');
process.exit(1);
}
createTestData(recordCount);
- 為程式碼集新增記錄。請在第 3 行,為應用程式程式碼中的 Logging API 模組新增以下參照:
const { Logging } = require("@google-cloud/logging");
檔案頂端的內容應如下所示:
const fs = require("fs");
const faker = require("faker");
const { Logging } = require("@google-cloud/logging"); //add this
- 現在,新增幾個常數變數,然後將 Logging 用戶端初始化。請將這些變數加到
const
陳述式正下方:
const logName = "pet-theory-logs-createTestData";
// Creates a Logging client
const logging = new Logging();
const log = logging.log(logName);
const resource = {
// This example targets the "global" resource for simplicity
type: "global",
};
- 新增程式碼,在 "console.log(
Created file ${fileName} containing ${recordCount} records.
);" 這行正下方,將記錄寫入 createTestData 函式中,看起來應會像這樣:
// A text log entry
const success_message = `Success: createTestData - Created file ${fileName} containing ${recordCount} records.`;
const entry = log.entry(
{ resource: resource },
{
name: `${fileName}`,
recordCount: `${recordCount}`,
message: `${success_message}`,
}
);
log.write([entry]);
- 成功更新後,
createTestData
函式的程式碼區塊應會像這樣:
async function createTestData(recordCount) {
const fileName = `customers_${recordCount}.csv`;
var f = fs.createWriteStream(fileName);
f.write('id,name,email,phone\n')
for (let i=0; i<recordCount; i++) {
const id = faker.datatype.number();
const firstName = faker.name.firstName();
const lastName = faker.name.lastName();
const name = `${firstName} ${lastName}`;
const email = getRandomCustomerEmail(firstName, lastName);
const phone = faker.phone.phoneNumber();
f.write(`${id},${name},${email},${phone}\n`);
}
console.log(`Created file ${fileName} containing ${recordCount} records.`);
// A text log entry
const success_message = `Success: createTestData - Created file ${fileName} containing ${recordCount} records.`;
const entry = log.entry(
{ resource: resource },
{
name: `${fileName}`,
recordCount: `${recordCount}`,
message: `${success_message}`,
}
);
log.write([entry]);
}
- 在 Cloud Shell 中執行下列指令,建立
customers_1000.csv
檔案,內含測試資料的 1000 筆記錄:
node createTestData 1000
您應該會收到類似下列的輸出內容:
Created file customers_1000.csv containing 1000 records.
- 開啟
customers_1000.csv
檔案,確認已建立測試資料。
測試已完成的工作
點選「Check my progress」 確認工作已完成。如果已成功為 Firestore 資料庫建立測試資料樣本,就會看到評估分數。
建立 Firestore 資料庫的測試資料
工作 4:匯入測試用顧客資料
- 如要測試匯入功能,請同時使用匯入指令碼,以及前面建立的測試資料:
node importTestData customers_1000.csv
您應該會收到類似下列的輸出內容:
Writing record 500
Writing record 1000
Wrote 1000 records
- 假設收到類似下方的錯誤:
Error: Cannot find module 'csv-parse'
請執行下列指令,在環境中加入 csv-parse
套件:
npm install csv-parse
- 然後再次執行指令。您應該會收到下列輸出內容:
Writing record 500
Writing record 1000
Wrote 1000 records
經過前面幾節課程說明,您已瞭解阿克和小茹是如何建立測試資料,以及將資料匯入 Firestore 的指令碼。
現在阿克將顧客資料載入 Firestore 資料庫時,可以比較放心了。
測試已完成的工作
點選「Check my progress」 確認工作已完成。
如果已成功將測試資料樣本匯入 Firestore 資料庫,就會看到評估分數。
將測試資料匯入 Firestore 資料庫
工作 5:檢查 Firestore 中的資料
在您和小茹的幫助下,阿克已成功將測試資料遷移到 Firestore 資料庫中。開啟 Firestore 看看結果吧!
- 返回 Cloud 控制台分頁。在「導覽選單」中,按一下「Firestore」。開啟 Firestore 後,按一下「鉛筆」圖示。

-
輸入 /customers
並按下 Enter 鍵。
-
重新整理瀏覽器分頁,您應會看到已成功遷移的顧客名單,如下所示:

恭喜!
在本實驗室課程中,您實際操作了 Firestore。產生一系列用於測試的顧客資料之後,您執行指令碼,將資料匯入 Firestore。接著,您也學到如何使用 Cloud 控制台控管 Firestore 中的資料。
Google Cloud 教育訓練與認證
協助您瞭解如何充分運用 Google Cloud 的技術。我們的課程會介紹專業技能和最佳做法,讓您可以快速掌握要領並持續進修。我們提供從基本到進階等級的訓練課程,並有隨選、線上和虛擬課程等選項,方便您抽空參加。認證可協助您驗證及證明自己在 Google Cloud 技術方面的技能和專業知識。
使用手冊上次更新日期:2024 年 2 月 28 日
實驗室上次測試日期:2024 年 2 月 28 日
Copyright 2025 Google LLC 保留所有權利。Google 和 Google 標誌是 Google LLC 的商標,其他公司和產品名稱則有可能是其關聯公司的商標。