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」 圖示 。
系統顯示視窗時,請按照下列步驟操作:
繼續操作 Cloud Shell 視窗。
授權 Cloud Shell 使用您的憑證發出 Google Cloud API 呼叫。
連線建立完成即代表已通過驗證,而且專案已設為您的 Project_ID : 。輸出內容中有一行文字,宣告本工作階段的 Project_ID :
Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}
gcloud
是 Google Cloud 的指令列工具,已預先安裝於 Cloud Shell,並支援 Tab 鍵自動完成功能。
(選用) 您可以執行下列指令來列出使用中的帳戶:
gcloud auth list
點按「授權」 。
輸出內容:
ACTIVE: *
ACCOUNT: {{{user_0.username | "ACCOUNT"}}}
To set the active account, run:
$ gcloud config set account `ACCOUNT`
(選用) 您可以使用下列指令來列出專案 ID:
gcloud config list project
輸出內容:
[core]
project = {{{project_0.project_id | "PROJECT_ID"}}}
注意: 如需 gcloud
的完整說明,請前往 Google Cloud 參閱 gcloud CLI 總覽指南 。
工作 1:在 Google Cloud 中設定 Firestore
阿克的工作是將 Pet Theory 的現有資料上傳到 Cloud Firestore 資料庫;他會與小茹密切合作來完成此目標。小茹收到來自阿克 IT 部門的訊息...
IT 管理員阿克
小茹你好:
採用無伺服器技術的第一步,是要使用 Google Cloud 建立 Firestore 資料庫。你能協助我順利完成這項工作嗎?我對這方面的設定不是很熟悉。
阿克
軟體顧問小茹
阿克你好:
沒問題,我很樂意幫忙。我會寄給你一些新手入門資源,你成功建立資料庫後,我們再聯絡。
小茹
請協助阿克透過 Cloud 控制台設定 Firestore 資料庫。
在 Cloud 控制台的「導覽選單」( ) 中,點選「查看所有產品」 ,然後選取「資料庫」 底下的「Firestore」 。
點選「建立 Firestore 資料庫」 。
選取「Standard 版」 。
在「設定選項」底下,選取「Firestore 原生模式」 。
在「安全性規則」部分,選擇「開啟」 。
在「位置類型」部分,點選「區域」 ,然後從清單中選取實驗室開頭設定 的區域。
注意: 如果畫面上未出現區域清單,請重新整理瀏覽器,或透過 Cloud 控制台選單再使用精靈一次。
附註: 這兩種模式雖有差別,且適合的用途也不同,但在同步一致方面的成效都很好。
其他設定都不更動,然後點選「建立資料庫」 。
完成這項工作後,小茹寄電子郵件給阿克...
軟體顧問小茹
阿克你好:
你設定 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」 ,接著點選「default」 資料庫。進入資料庫後,按一下鉛筆圖示。
輸入 /customers
並按下 Enter 鍵。
重新整理瀏覽器分頁,您應會看到已成功遷移的顧客名單,如下所示:
恭喜!
在本實驗室課程中,您實際操作了 Firestore。產生一系列用於測試的顧客資料之後,您執行指令碼,將資料匯入 Firestore,並學會如何透過 Cloud 控制台控制 Firestore 中的資料。
Google Cloud 教育訓練與認證
協助您瞭解如何充分運用 Google Cloud 的技術。我們的課程 會介紹專業技能和最佳做法,讓您可以快速掌握要領並持續進修。我們提供從基本到進階等級的訓練課程,並有隨選、線上和虛擬課程等選項,方便您抽空參加。認證 可協助您驗證及證明自己在 Google Cloud 技術方面的技能和專業知識。
使用手冊上次更新日期:2025 年 5 月 6 日
實驗室上次測試日期:2025 年 5 月 6 日
Copyright 2025 Google LLC 保留所有權利。Google 和 Google 標誌是 Google LLC 的商標,其他公司和產品名稱則有可能是其關聯公司的商標。