在暸解了資料庫儲存概念,以及比較核心的文件、集合與參照後,今天就來跟著官方文件提供的案例,研究怎麼在消化這些知識後,簡單規劃一個聊天室資料的儲存方式,進而暸解怎麼分層資料結構在 Cloud Firestore 是怎麼運作的吧。
首先,我們會有很多聊天室,所以我們在資料故底層建立一個叫做 rooms 的集合。並在裡面存放一個個儲存聊天室相關資訊的文件。這邊先只存放聊天室名稱作為示例,詳細可能還有更多資訊要儲存。
# 這邊用全大寫與方括號包覆表示其為集合、大駝峰表示文件、
# 蛇式命名法表示欄位,方便讀者釐清。
[ROOMS]:
RoomA:
name: "若虛的聊天室"
RoomB:
name: "鐵人競賽專用聊天室"
....
好,現在我們要來思考怎麼存放聊天室的訊息了,畢竟這才是聊天室最重要的部分。那我們是要在聊天室的一個欄位建立 Array 型別的欄位,然後在該欄位裡面放置一個個 Map 型別的資料去儲存訊息嗎?
# 這邊用全大寫與方括號包覆表示其為集合、大駝峰表示文件、
# 蛇式命名法表示欄位,方便讀者釐清。
[ROOMS]:
RoomA:
name: "若虛的聊天室"
messages:
- text: "hello, world"
sender: "Roushi"
created_at: "2018-10-27 23:42"
- text: "Cool"
created_at: "2018-10-27 23:43"
sender: "Roushi"
當我們想要把大量的訊息資料存在一個聊天室文件裡時,就要注意了,因為 Cloud Firestore 的哲學本身不鼓勵把大量資料存在同一份文件裡,記得我們前天暸解到的一個重要資訊嗎——文件的大小最多只能到 1MB。也就說,Cloud Firestore 認為每個文件都應該要保持輕量,把所有聊天室訊息存在文件裡是違反這個理念的。
那我們該怎麼做呢?這時候又要來回憶了,在「資料庫儲存概念」中我們暸解到文件是存放在集合裡,而文件又可以擁有多個子集合。既然文件本身必須維持輕量,那我們就只把每個訊息與其相關資訊寫成一個文件,然後再把這些文件放在聊天室文件的子集合吧!
# 這邊用全大寫與方括號包覆表示其為集合、大駝峰表示文件、
# 蛇式命名法表示欄位,方便讀者釐清。
[ROOMS]:
RoomA:
name: "若虛的聊天室"
[MESSAGES]:
Message001:
text: "hello, world"
created_at: "2018-10-27 23:42"
sender: "Roushi"
Message002:
text: "Cool"
created_at: "2018-10-27 23:43"
sender: "Roushi"
如此一來,我們就能讓每個文件都保持輕量,又能將大量的資料儲存在文件之下了。最後,讓我們活用昨天暸解到參照,去暸解一下怎麼取的訊息的參照吧!一樣透過 JS 和 Ruby 作為範例程式碼做舉例:
// JS
let messageReference = db.collection('ROOMS').doc('RoomA')
.collection('MESSAGES').doc('Message001')
# Ruby
message_reference = firestore
.col('ROOMS').doc('RoomA')
.col('MESSAGES').doc('Message001')