You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 10:15:33