Firebase是專為行動應用打造的雲端平台,雖有其收費機制,但仍有提供部份免費流量。加上Angular 6也已將Firebase資料庫存取的程式碼納入專案中(@angular/fire,原為angularfire2套件),故以ionic-angular為主體的Ionic 4 App,拿Firebase做為雲端資料庫平台,在開發上可說十分方便。
然而,Firebase新版資料庫Cloud Firestore屬於NoSQL文件資料庫(No SQL document database),運作方式與傳統關聯式資料庫有所不同。其中最大的差異之一是Firestore沒有「自動遞增」,而是以亂數編碼產生unique id。
因此,一旦需要類似員工編號這類不能重複的流水號,在firestore資料庫裡便要自行建立「自動遞增」(auto increment) 機制。本文將介紹以cloud functions實做database trigger,在新增一筆文件時,便會觸發cloud function,在文件加入編號欄位,同時更新流水號。
前置動作
需先至Firebase控制台新增專案,並啟用Cloud Firestore資料庫。進入Firestore資料庫建立counters集合,在其下新增文件users,內有count欄位;該欄位用來儲存自動遞增流水號。另外,也建立users集合,如下圖所示:
在Firestore建立couters/users文件,內有count欄位,用以儲存自動遞增流水號 |
建立cloud functions
由於cloud functions是儲存在Firebase平台上,故需以firebase-tools建立,最後還必須佈署到雲端,相關步驟如下:npm install -g firebase-tools firebase login以google帳號登入後,即可使用firebase CLI工具,建立cloud functions。
firebase init functions
新增cloud functions過程需做"Project Setup"與"Functions Setup"兩部份,依照步驟指示逐一設定即可。"Project Setup"步驟如下圖,需選定對應專案:
![]() |
專案設定:用上下鍵選擇想要關聯的Firebase專案 |
"Functions Setup"則分為幾個步驟,其中最重要的是選擇程式語言JavaScript或TypeScript,本文選擇JavaScript (Firebase使用Node.js) :
![]() |
Functions設定:選擇JavaScript語言、使用TSLint、立即安裝相依套件 |
index.js程式碼如下:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'user strict' | |
const functions = require('firebase-functions'); | |
const admin = require('firebase-admin'); | |
// Prevent firebase from initializing twice | |
try { | |
admin.initializeApp(functions.config().firebase) | |
} catch (e) {} | |
var db = admin.firestore(); // firestore db | |
// Prevent the app breaking from the upcoming behavioral changes of Date Objects | |
const settings = { | |
timestampsInSnapshots: true | |
}; | |
db.settings(settings); | |
const counterRef = db.collection('counters').doc('users'); // 員工編號counter | |
// user record creation trigger | |
exports.userCreateTrigger = functions.firestore.document('users/{uid}') | |
.onCreate((snap, context) => { | |
return db.runTransaction( t => { // transaction | |
var userRef = snap.ref; // reference of 新增文件 | |
return t.get(counterRef).then(doc => { // 讀取current counter | |
var currentId = doc.data().count; // 目前counter值 | |
var uidString = "E" + ("00000" + currentId).slice(-5); // 員工編號:E00001開始 | |
t.update(userRef, { // Step 1:設定員工編號 | |
uid: uidString | |
}); | |
const newId = currentId + 1; // counter+1 | |
t.update(counterRef, { // Step 2:更新counter | |
count: newId | |
}); | |
}); | |
}); | |
}); |
- 第3-4行:cloud functions功能也就是事件驅動的部份,例如新增一份文件的事件,是透過'firebase-functions'提供,但資料庫firestore的存取則是在'firebase-admin',故需require兩者。
- 第6行:cloud functions初始化。
- 第11行:admin.firestore()取得資料庫參考變數。
- 第22-23行:functions.firestore.document(document)是用來登錄資料庫寫入動作的觸發處理器,其中.onCreate(snap, context)是新增一份文件的觸發處理器。詳情可參考:Cloud Firestore事件。
- 第24行:由於文件新增時,cloud function必須完成 (1)讀取counter,(2) 更新文件加入員工編號欄位 (3)更新counter(遞增),故必須用transaction處理。
- 第25行:snap.ref為此次新增文件的參考變數,透過它才能加入員工編號。
- 第27-28行:動作(1) 讀取目前的counter(位於counters/users的count欄位)。
- 第29-32行:動作(2) 將員工編號加入文件中。
- 第33-36行:動作(3) 更新counter。
執行下列指令,將cloud functions佈署到Firebase雲端平台:
firebase deploy --only functions
佈署成功後,便可從雲端平台手動加入一份文件到users集合,並從Functions功能裡查看訊息:
查看事件訊息 |
firebase-tools: 5.0.1
Cloud Functions API 2.0
延伸閱讀:
- Cloud Functions建立範例:https://firebase.google.com/docs/functions/get-started
- Cloud Firestore事件
- Distributed counters範例
沒有留言:
張貼留言