Firestore嵌套文档onDocumentCreated触发时更新父文档的问题咨询
我最近碰到个Firestore的问题,想请教下各位。具体场景是这样的:我需要统计每个国家的城市数量,所以给/countries/{countryId}/cities/{cityId}这个路径注册了onDocumentCreated触发器,打算每次有新城市创建时,把对应国家文档里的cityCount字段加1。
原本我计划用事务来更新这个计数,但发现当某个国家的第一个城市被创建时,对应的父文档/countries/{countryId}居然还不存在,直接导致事务执行失败了。
我查过Firestore的官方文档,里面明明说:
Collections and documents are created implicitly in Cloud Firestore.
Simply assign data to a document within a collection.
If either the collection or document does not exist, Cloud Firestore creates it.
我写了一段测试代码验证这个情况,结果显示新创建的城市文档确实存在,但对应的国家文档不管是通过snapshot.ref.parent.parent获取引用查询,还是直接用db.doc()构造路径去查询,结果都是不存在的——数据返回undefined,exists字段也是false。代码如下:
const {onDocumentCreated} = require("firebase-functions/v2/firestore"); const {initializeApp, getApps} = require("firebase-admin/app"); const {getFirestore, DocumentReference} = require("firebase-admin/firestore"); if (!getApps().length) initializeApp(); const db = getFirestore(); exports.firestoreEventHander = onDocumentCreated( "countries/{countryId}/cities/{cityId}", async (event) => { const snapshot = event.data; console.log("snapshot exists:", snapshot.exists); // true const countryRef = snapshot.ref.parent.parent; console.log("country path:", countryRef.path); // countries/USA // Access snapshot through the db const cityDoc = await db.doc(`countries/${countryId}/cities/${cityId}`).get(); console.log("cityDoc.exists:", cityDoc.exists); // true // Check if the countryRef document exists const countryDoc = await countryRef.get(); console.log("countryDoc:", countryDoc.data()); // ⚠️ undefined ⚠️ console.log("countryDoc.exists:", countryDoc.exists); // ⚠️ false ⚠️ // Try to access the country via db.doc() const countryDoc2 = await db.doc(`countries/${countryId}`).get(); console.log("countryDoc2:", countryDoc2.data()); // ⚠️ undefined ⚠️ console.log("countryDoc2.exists:", countryDoc2.exists); // ⚠️ false ⚠️ }, );
另外我看官方的“Trigger a function when a new document is created”示例里,完全没提到创建嵌套文档时父文档可能不存在这种情况。想问问大家,这种场景下应该怎么正确更新父文档的cityCount呢?
备注:内容来源于stack exchange,提问作者Dan Dascalescu

