{%hackmd @wh91008/theme %} # Lecture 4 - Firestore的監聽(onSnapshot) ###### tags: `GCP` `Firestore` `Cloud Function` `Python` [TOC] --- ## ==一、前言== 從前面幾個章節中,我們學會自行新增、修改、查詢、刪除資料,也學會設使用Query抓取符合某些條件的資料。除此之外,Firestore有個非常好用的功能就是 **「監聽」**,簡單來說,監聽就是讓我們可以設定出我們需要觸發某個事件的條件,並且在事件發生後,因為 **監聽的存在** 而自動執行我們設定的東西。 例如: 要如何讓資料庫被匯入資料時,則自動print出更新後的資料? 要如何讓資料庫中產生符合某種類型的資料時(搭配[第三章Query](https://hackmd.io/ahMSiVVBSamqePG8ePDKIA)),就print出那條資料? --- ## ==二、監聽的方法== 一般而言,監聽的方法可分為兩種: 1. ```onSnapshot```:與 ```get()``` 方法不同,```onSnapshot``` 可以即時監聽資料庫的變化,只要有變化就會立刻傳送指定的資料,相比於Cloud Function,```onSnapshot``` 主要於本機端做運算。 2. ```Cloud Function```:基本上宗旨是「在無伺服器的環境中打造並連結雲端服務」,可以根據觸發條件的不同,來監聽 Firestore 的變化。可以事先將程式的邏輯建置在Cloud Function上,一旦某些事件的發生(如 ```write```、```create```、```update```、```delete```),就會運行所建置的程式邏輯。 **此章節將專注於onSnapshot的講解,關於Cloud Function的各種資訊,可詳見:** :::success 1. **建置Cloud Function** - Node.js: [第五章 - Cloud Function的入門與部署(Node.js)](https://hackmd.io/vZahd2ElQmmorHGD3GxEug) - Python: [第五章 - Cloud Function的入門與部署(Python)](https://hackmd.io/yn10QCzJS8yqbe8twZGCFQ) 2. **使用Cloud Function進行監聽**:[第六章 - Firestore的監聽(Cloud Funtion)](https://hackmd.io/dspKO4cPSQaOpUCt-eZgTg?both) 3. **Cloud Function的延伸應用**:[第七章 - Cloud Function的延伸應用](https://hackmd.io/SaNljmR7TRy_E8hyoRYXzQ?both) ::: ###### :book: 參考資料: ###### 1. Get realtime updates with Cloud Firestore https://firebase.google.com/docs/firestore/query-data/listen?hl=zh-cn ###### 2. Cloud Functions 的介紹與應用 https://blog.gcp.expert/cloud-functions-introduction/ --- ## ==三、on_Snapshot的介紹(先跳過)== 如同前面所述,```onSnapshot``` 方法可以 **「即時監聽資料庫的變化」** ,只要有變化就會立刻傳送指定的資料。 詳細內容可以參考 [這篇文章](https://www.oxxostudio.tw/articles/201905/firebase-firestore.html) ,雖然不是python的寫法,不過有相當詳盡的介紹 ### (一)監聽並回傳document 如下面官方所釋出的文件中可以看到,使用 ```on_snapshot()``` 做監聽後,可再呼叫並回傳更新後的doc ```python= # Create a callback on_snapshot function to capture changes def on_snapshot(doc_snapshot, changes, read_time): for doc in doc_snapshot: print(u'Received document snapshot: {}'.format(doc.id)) doc_ref = db.collection(u'cities').document(u'SF') # Watch the document doc_watch = doc_ref.on_snapshot(on_snapshot) ``` ### (二)Events for local changes(Python未更新) 因為監聽存在,所以通常只要寫入資料就會馬上調用snapshot listeners,主要是因為一個叫做「延遲補償」的重要功能,在執行寫入的操作時,數據還沒發送到後端,系統就已經會通知listeners即將有新的數據。 document有一個叫做```metadata.hasPendingWrites```的語法,能告訴document是否有更改的資料還沒被寫入後端,也能使用這個語法來確定snapshot listeners將接收到的事件來源。 ```python= // Not yet supported in Python client library ``` ### (三)Events for metadata changes(Python未更新) 在偵聽對文檔、集合或查詢的更改時,您可以傳遞選項來控制偵聽器將接收到的事件的粒度。 默認情況下,系統不會就僅影響元數據的變更通知偵聽器。考慮當您的應用寫入新文檔時會發生什麼情況: 新數據立即觸發更改事件。該文檔尚未寫入後端,因此“待寫入”標誌為true。 該文檔寫入後端。 成功寫入後,後端通知客戶端。文檔數據沒有變化,但因為“待寫入”標誌現在為false,產生了一項元數據更改。 如果您希望在文檔或查詢元數據發生更改時均收到快照事件,請在連接偵聽器時傳遞偵聽選項對象: Web ```python= // Not yet supported in Python client library ``` ### (四)監聽搭配Query 在監聽的同時也可設定 [Query條件](https://hackmd.io/ahMSiVVBSamqePG8ePDKIA#Firestore%E7%9A%84%E6%B5%81%E9%87%8F%E7%AF%80%E7%9C%81%EF%BC%88Query%EF%BC%89) 來做資料的篩選 ```python= # Create a callback on_snapshot function to capture changes def on_snapshot(col_snapshot, changes, read_time): print(u'Callback received query snapshot.') print(u'Current cities in California:') for doc in col_snapshot: print(u'{}'.format(doc.id)) col_query = db.collection(u'cities').where(u'state', u'==', u'CA') # Watch the collection query query_watch = col_query.on_snapshot(on_snapshot) ``` ### (五)監聽資料的變化 可以利用資料變化 type 的 name ,來分類出資料是如何變化、變化了什麼(例如資料被```ADDED``` 、```MODIFIED```、```REMOVED```...等) ```python= # Create a callback on_snapshot function to capture changes def on_snapshot(col_snapshot, changes, read_time): print(u'Callback received query snapshot.') print(u'Current cities in California: ') for change in changes: if change.type.name == 'ADDED': print(u'New city: {}'.format(change.document.id)) elif change.type.name == 'MODIFIED': print(u'Modified city: {}'.format(change.document.id)) elif change.type.name == 'REMOVED': print(u'Removed city: {}'.format(change.document.id)) col_query = db.collection(u'cities').where(u'state', u'==', u'CA') # Watch the collection query query_watch = col_query.on_snapshot(on_snapshot) ``` :::warning :bulb: **小提醒** 如果監聽 document 時 設定條件為「回傳 有更改 的 document」時,它實際上會回傳好幾個,不過只有有更改的那個有計費 ::: ### (六)停止監聽 不需監聽數據時,則輸入以下函數,其中```doc_watch```須改為自己監聽的變數名稱: ```python= # Terminate watch on a document doc_watch.unsubscribe() ``` ### (七)處理監聽錯誤(Python未更新) 監聽有時可能會失敗,可能的原因有很多(例如:安全權限、查詢的函數本身監聽無效。),要處理這些問題,則可以在監測時就提供錯誤回調函數。發生錯誤後,監聽器將不再收到任何事件,因此無需分離偵聽器。 ###### :book: 參考資料: ###### 1. 使用Cloud Firestore 獲取實時更新 https://firebase.google.com/docs/firestore/query-data/listen?hl=zh-cn
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up