为何Firestore生成的时间戳写入Realtime Database时拆分为两个节点?
问题:Firestore时间戳复用至Realtime Database时存储异常
我使用以下函数获取Firestore服务器时间戳:
FieldValue getFirestoreTimestamp() { return FieldValue.serverTimestamp(); }
将该值同时用于Firestore和Realtime Database时,Firestore中能正常写入,显示为Jul 25, 2023 08:33 PM,但Realtime Database出现问题:通过Firestore触发器同步数据时,本想复用同一时间戳保证一致性,结果写入时未作为单个节点存储。预期格式为createdAdminTimestamp: 1690337178000,实际却被拆分为两个节点。
触发写入的代码如下:
function firestoreTrigger() { ... const createDate = documentData.createDate; await setGroupAdminRTDB(groupID, adminUID, adminUsername, createDate); ... } async function setGroupAdminRTDB( groupID: string, adminUID: string, adminUsername: string, createdAdminTimestamp: number ): Promise<{ returnVal: number; returnMsg: string }> { let returnVal = 0; let returnMsg = ""; const nodeRef = await admin .database() .ref("app/groups/" + groupID + "/admin/") .once("value"); const data = nodeRef.val(); if (data == null) { try { const adminData = { adminUsername: adminUsername, createdAdminTimestamp: createdAdminTimestamp, }; await admin .database() .ref("app/groups/" + groupID + "/admin/" + adminUID) .set(adminData); returnVal = 1; returnMsg = "Data successfully added!"; } catch (error) { returnVal = 0; returnMsg = "ERROR: " + error; } } else { returnVal = 0; returnMsg = "Error: data already exists at admin node"; } return { returnVal: returnVal, returnMsg: returnMsg }; }
问题原因
FieldValue.serverTimestamp()是Firestore专属的占位符对象,写入Firestore后会被解析为Firestore的Timestamp类型(包含_seconds和_nanoseconds两个内部字段)。在触发器中读取documentData.createDate时,拿到的是这个Timestamp对象而非直接的数值,直接传入Realtime Database会被自动拆分为两个节点存储。
解决步骤
- 转换Timestamp为毫秒级数值
在触发器中读取到Firestore的Timestamp后,将其转换为Realtime Database支持的毫秒级时间戳:function firestoreTrigger() { ... // 将Firestore Timestamp转换为毫秒数 const timestampMs = documentData.createDate.toDate().getTime(); await setGroupAdminRTDB(groupID, adminUID, adminUsername, timestampMs); ... } - 确保类型匹配
函数setGroupAdminRTDB的参数createdAdminTimestamp已定义为number,转换后的毫秒数刚好符合该类型,写入Realtime Database时会作为单个节点存储,满足预期格式。
额外建议
如果客户端需要同时写入两个数据库,建议在客户端直接生成统一的时间戳(比如Date.now()),再分别传给Firestore和Realtime Database,无需依赖Firestore的服务器时间戳,能进一步保证数据一致性。
内容的提问来源于stack exchange,提问作者whatwhatwhat
相关产品推荐
相关产品推荐

