Swift实现Firestore数据24小时后自动恢复初始值
Firestore文档数据24小时自动恢复实现方案
一、调整文档数据结构
不要直接覆盖原始数据,而是拆分存储初始值、临时值和过期时间,避免原始数据丢失。示例文档结构如下:
{ "originalName": "Michael", // 永久保存的初始值 "tempName": "Andrew", // 用户设置的临时值 "tempExpireAt": "<Timestamp>" // 临时值过期时间(当前时间+24小时) }
二、Swift端修改临时数据逻辑
用户发起修改请求时,先确保初始值已存储,再写入临时值和过期时间:
import FirebaseFirestore func updateTempUserName(userId: String, newTempName: String) async throws { let db = Firestore.firestore() let userDocRef = db.collection("users").document(userId) // 读取或初始化原始名称 let docSnapshot = try await userDocRef.getDocument() var originalName: String if let existingOriginal = docSnapshot.data()?["originalName"] as? String { originalName = existingOriginal } else { // 首次设置时,将当前名称作为初始值(可根据业务调整来源) originalName = docSnapshot.data()?["name"] as? String ?? "DefaultName" try await userDocRef.setData(["originalName": originalName], merge: true) } // 设置临时名称和24小时后过期的时间戳 let expireDate = Date().addingTimeInterval(24 * 60 * 60) try await userDocRef.setData([ "tempName": newTempName, "tempExpireAt": Timestamp(date: expireDate) ], merge: true) }
三、自动恢复核心实现(两种方案)
方案1:Cloud Functions定时触发(推荐)
通过Cloud Functions的定时任务,周期性扫描过期的临时数据,批量恢复原始值:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.resetExpiredTempData = functions.pubsub.schedule('every 1 hours').onRun(async (context) => { const db = admin.firestore(); const now = new Date(); // 查询所有临时数据已过期的文档 const querySnapshot = await db.collection("users") .where("tempExpireAt", "<=", now) .get(); // 批量更新恢复原始值 const batch = db.batch(); querySnapshot.forEach(doc => { const originalName = doc.data().originalName; batch.update(doc.ref, { "name": originalName, "tempName": admin.firestore.FieldValue.delete(), "tempExpireAt": admin.firestore.FieldValue.delete() }); }); await batch.commit(); functions.logger.log(`完成${querySnapshot.size}个过期临时数据的重置`); return null; });
方案2:客户端辅助校验(补充体验)
为避免Cloud Functions延迟导致用户看到过期数据,客户端读取时主动校验并恢复:
func fetchUserName(userId: String) async throws -> String { let db = Firestore.firestore() let userDocRef = db.collection("users").document(userId) let docSnapshot = try await userDocRef.getDocument() guard let data = docSnapshot.data() else { throw NSError(domain: "FirestoreError", code: -1, userInfo: [NSLocalizedDescriptionKey: "用户文档不存在"]) } let originalName = data["originalName"] as? String ?? "DefaultName" // 检查临时数据是否有效 if let tempName = data["tempName"] as? String, let expireTimestamp = data["tempExpireAt"] as? Timestamp, Date() < expireTimestamp.dateValue() { return tempName } else { // 临时数据过期,手动恢复并返回原始值 try await userDocRef.updateData([ "name": originalName, "tempName": FieldValue.delete(), "tempExpireAt": FieldValue.delete() ]) return originalName } }
四、关键注意事项
- 权限控制:在Firestore安全规则中限制仅用户本人可修改自己的文档:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow read, update: if request.auth != null && request.auth.uid == userId; } } }
- 时区统一:所有时间处理使用UTC时区,避免时区差异导致过期时间偏差。
- 批量操作:处理大量过期文档时必须用批量写入,避免触发Firestore单请求限制。
内容的提问来源于stack exchange,提问作者mickele29
相关产品推荐
相关产品推荐

