如何将Firestore serverTimestamp存为毫秒整数并实现时间条件查询
Firestore 服务端时间戳使用方案
一、将服务端时间转换为毫秒整数存储的实现方式
因为firebase.firestore.FieldValue.serverTimestamp()是服务端生成的哨兵值,写入时客户端无法直接拿到毫秒值,可通过以下两种方式实现:
- 方式1:新增云函数自动转换
配置Firestore文档创建触发器,当消息文档写入完成后,自动将原生Timestamp类型转换为毫秒整数存入单独字段,示例云函数代码:
后续存储、查询都使用exports.convertTimestamp = functions.firestore .document('messages/{messageId}') .onCreate((snap, context) => { const timestamp = snap.get('timestamp'); return snap.ref.update({ timestamp_ms: timestamp.toMillis() }); });timestamp_ms整数字段即可,和你之前用Date.now()的逻辑完全兼容。 - 方式2:读取时动态转换
不额外存储整数字段,读取到Timestamp对象后调用toMillis()方法,即可得到和Date.now()格式完全一致的毫秒整数:const timestampInt = doc.data().timestamp.toMillis();
二、使用原生Timestamp进行查询的实现方案
不需要修改存储逻辑,仅调整查询参数即可解决过滤问题:
Firestore的原生Timestamp类型支持直接进行大小对比,查询时将你本地存储的整数类型lasttimekey转换为Timestamp对象即可正常执行条件过滤,修改后的查询代码如下:
var loadnewmessages = messagesRef.orderBy("timestamp") // 将整数时间戳转换为Firestore支持的Timestamp对象 .where("timestamp", ">", firebase.firestore.Timestamp.fromMillis(parseInt(lasttimekey))) .limit(50) .onSnapshot((snapshot) => { // 原有业务逻辑无需修改 snapshot.docChanges().forEach((change) => { if(change.type === "added"){ // 若需要用到整数时间戳,调用change.doc.data().timestamp.toMillis()即可 ... } }) })
该方案不需要额外维护字段,所有时间均由服务端统一生成,可完全解决多设备本地时间不一致导致的消息重复问题。
内容的提问来源于stack exchange,提问作者Kubaguette The Testobun
相关产品推荐
相关产品推荐

