---
# System prepended metadata

title: Lecture 6 - Firestore的監聽（Cloud Funtion）
tags: [GCP, Firestore, Cloud Function, Python]

---

{%hackmd @wh91008/theme %}

# Lecture 6 - Firestore的監聽（Cloud Funtion）

###### tags:  `GCP` `Firestore` `Cloud Function` `Python`

[TOC]

---
## ==一、前言==
筆者在 [第四章 - Firestore的監聽（onSnapshot）](https://hackmd.io/8_Z5qQVfTBugi6xlzbQF3Q#%E4%B8%80%E3%80%81%E5%89%8D%E8%A8%80) 已經提過 Firestore 有個非常好用的功能就是 「監聽」，其中其中一個方法是搭配 Cloud Function 進行監聽，此章節就是用來介紹 「Cloud Function 要如何進行監聽？」

前置作業與監聽方法的簡介也可參考第四章，在此不再多做贅述

---


## ==二、使用Cloud Function 監聽 Firestore==
在不論是使用 [Python](https://hackmd.io/yn10QCzJS8yqbe8twZGCFQ) 或是 [Node.js](https://hackmd.io/vZahd2ElQmmorHGD3GxEug) ，第五章我們已經成功佈署了 Cloud Function 的第一個函數，接著就可以直接透過網頁版的Cloud Function介面來做其他函數的佈署，佈署介面如下：

![](https://i.imgur.com/DQ3xqv3.png =600x)

在使用Cloud Function進行監聽時，有個非常重要的地方就是 **「觸發條件」與「事件類型」** （甚至可以說是進行監聽最重要的一個環節），且一旦部署函式後，將 **不容更改** ，所以請務必在部署之前就先確認好所需使用的條件與事件類型。

### （一）事件類型
在此將先以觸發條件為Cloud Firestore的情況下，詳述各個事件類型的差異，事件類型分為：

- write：寫入
- create：創建
- update：更新
- delect：刪除

如同字面上的意思，當指定的文件路徑（也就是被監聽的地方）發生該事件時，則就會執行 ```main.py``` 中所指定的 **某個函式** 。

### （二）文件路徑
假設資料結構呈現如下：
![](https://i.imgur.com/tVB6GwE.png)

監聽主要會分為兩個情況：
1.  **監聽document** ：只監聽某個document（例如match1055）裡的變化，則文件路徑為 ```PlayAndScore/match1055```
2.  **監聽collection** ：監聽整個collection裡面的情況，例如要建構遊戲常常會需要增加很多match，則監聽collection就能在一個match產生後執行指定的函式（進行主遊戲、開始紀錄...等），則文件路徑為```PlayAndScore/{隨便輸入但不可以為空或奇怪的符號}```。

### （三）呼叫函式

在確認好事件類型與監控的文件路徑後，最靈魂的部分就是呼叫函式，首先在```requeirements.txt```中，必須先輸入依附元件的名稱與版本，格式如下：
```python=
# Function dependencies, for example:
# package>=version
requests == 2.18.4
pandas == 0.25.0
firebase-admin == 2.17.0
numpy == 1.17.0
asyncio == 3.4.3
```
接著在```main.py```中輸入所有的程式
```python=
# TODO import some packages
import asyncio
import time
import requests
import pandas as pd
import numpy as np
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
import json

# TODO use the application default credentials
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred, {
    'projectId': '?????',
}) # projectId可從 一般設定 獲取 專案專屬識別碼

# TODO function
def hello_firestore(event, context):
    """Triggered by a change to a Firestore document.
    Args:
         event (dict): Event payload.
         context (google.cloud.functions.Context): Metadata for the event.
    """
    resource_string = context.resource
    # print out the resource string that triggered the function
    print(f"Function triggered by change to: {resource_string}.")
    # now print out the entire event object
    print(str(event))
```
最後，就可以在最下方 **要執行的函式** 中輸入該指定函式
:::warning
:bulb: 小提醒：
1. 在```main.py```中可以寫入很多function，但最前方要記得import Package與輸入專案認證的部份，且最後執行函式只能寫一個。
2. 函式是否有執行成功，可點擊「測試」確認是否回應ok，若回應ok則前往「查看紀錄」中可觀看相關的紀錄檔，確保函式沒有bug存在。
:::
---
其他函式實用的補充資訊，可參考至 [第七章 - Cloud Function的延伸應用](https://hackmd.io/SaNljmR7TRy_E8hyoRYXzQ?both)，會有更詳細的解釋和持續的更新。
