【问题标题】:Splitting up Firebase Snapshots into smaller pieces?将 Firebase 快照拆分成更小的部分?
【发布时间】:2020-12-10 10:45:30
【问题描述】:

出于测试目的,我在 Firebase 数据库上创建了一个特定节点。我将用户复制到该节点,然后可以使用它而不用担心损坏数据或破坏用户信息。它非常适合我的目的。

不过,我遇到了一个问题。如果用户拥有非常大的数据集,则复制功能将不起作用。它只是停滞不前。不过,我没有收到任何错误。我读到 Firebase 的复制限制为 1MB,我猜这就是问题所在。我想我正撞墙。

这是我的代码:

func copyToTestingNode() {
    
    let start = Date()

    // 1 . create copy of user and then modify the copy
    guard var copiedUser = user else { print("copied user error"); return }
    copiedUser.userID = MP.adminID
    copiedUser.householdInfo.subscriptionExpiryDate = 2500000000
    
    // 2. get a snapshot of the copied user's info
    ref.child(user.userID).observeSingleEvent(of: .value) { (userSnapshot) in
        
        print("Step 2 TRT:", Date().timeIntervalSince(start))

        // 3. remove any existing data at admin node, and then...
        self.ref.child(MP.adminID).removeValue { (error, dbRef) in
            
            print("Step 3 TRT:", Date().timeIntervalSince(start))

            // 4. ...copy the new user info to the admin node
            self.ref.child(MP.adminID).setValue(userSnapshot.value, withCompletionBlock: { (error, adminRef) in
                
                print("Step 4 TRT:", Date().timeIntervalSince(start))

                // 5. then send user alert and stop activity indicator
                self.activityIndicator.stopAnimating()
                self.showSimpleAlert(alertTitle: "Copy Complete", alertMessage: "Your copy of \(copiedUser.householdInfo.userName) is complete and can be found under the new node:\n\n\(copiedUser.householdInfo.userName) Family")
            })
        }
    }
}

选项:

  1. 有没有一种简单的方法来检查DataSnapshot 的大小以提醒我数据集太大而无法复制?

  2. 有没有一种简单的方法可以将快照拆分成更小的部分并通过这种方式克服 1MB 的限制?

  3. 我应该使用 Cloud Functions 而不是尝试在设备上触发它吗?

  4. 有没有办法以某种方式将快照“压缩”得更小,以便我可以更轻松地复制它?

我愿意接受建议。

更新 #1

  1. 我了解到HERE 的大小限制。从弗兰克的反应来看,我猜我对这个限制的理解是错误的。

  2. 我从 Firebase 控制台下载了节点并检查了它的大小。我的硬盘上有 799 KB。这是一个很大的 JSON 树,所以我认为它的大小一定是它不会复制的原因。较小的节点复制过来没有问题。只有大的有麻烦。

更新 #2

我不确定如何显示实际数据,除了屏幕截图,看看 JSON 树有多大。所以这里是截图:

如您所见,数据有多个节点,其中一些节点比其他节点大。我想我可以减少“Job Jar”节点,但其余部分确实需要达到这个大小才能使一切正常工作。

当然,这是我所有用户中最大的数据集之一,但结构没有改变。

至于每行代码的执行速度,这里是每个编号步骤的模拟器时间:

第 2 步 TRT:0.5278879404067993

第 3 步 TRT:0.6249579191207886

第 4 步 TRT:1.8466829061508179

复制完毕!!

这仅适用于较小的数据集。对于较大的,我从来没有到第 4 步。它只是挂起。我让它运行了几分钟,但没有任何变化。

【问题讨论】:

  • 1) “我读到 Firebase 的复制限制为 1MB” 您在哪里看到的? 2) 我建议不要假设节点的大小是问题,而是下载节点(Firebase 控制台中有下载它的链接)并检查它的大小。
  • @FrankvanPuffelen,我回答了您的问题,作为上述问题的更新。
  • 该文档链接中唯一提到的 1MB 限制是关于 Cloud Functions 的触发器。由于您尚未使用 Cloud Functions,因此该限制不会导致此问题。
  • 800KB 是相当多的 JSON,但应该可以在大多数现代设备上加载。不过,这在一定程度上取决于结构,因为它不只是作为单个 800KB 字符串保存在内存中。如果您向我们展示实际数据并展示一些调试结果,例如每行代码执行需要多长时间,我们更有可能提供帮助。这也将使我们有机会考虑您的第二个问题,这可能涉及某种querylimit
  • @FrankvanPuffelen 这正是我选择做的。我只是选择一次将snapshot.children 移到一个以上。没问题。似乎工作得很好。旁注:我确实必须删除步骤 3 中的数据。如果我只是覆盖,一些用户没有所有数据节点,因此以前的用户数据仍然存在。谢谢你的帮助。

标签: swift firebase firebase-realtime-database google-cloud-functions


【解决方案1】:

似乎可行的最终版本:

func copyToTestingNode() {
            
    // 1 . create copy of user and then modify the copy
    guard var copiedUser = user else { print("copied user error"); return }
    let adminRef = ref.child(MP.adminID)
    copiedUser.userID = MP.adminID
    copiedUser.householdInfo.subscriptionExpiryDate = 2500000000
    
    // 2. get a snapshot of the copied user's info
    ref.child(user.userID).observeSingleEvent(of: .value) { (userSnapshot) in
                    
        // 3. remove any existing data at admin node, and then...
        adminRef.removeValue { (error, dbRef) in
            
            if (error != nil) { print("Yikes!") }

            // 4. ...copy the new user info to the admin node one node at a time (if user has a lot of data)
            var totalNodesCopied = 0
            
            for item in userSnapshot.children {
                guard let snap = item as? DataSnapshot else { print("snap error"); return }
                
                self.ref.child(MP.adminID).child(snap.key).setValue(snap.value) { (error, adminRef) in
                    
                    totalNodesCopied += 1
                    
                    if totalNodesCopied == userSnapshot.childrenCount {
                        print("ALL DONE COPYING!!")
                    }
                }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2016-11-08
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    相关资源
    最近更新 更多