Firebase:下次应用启动时如何仅检索已更改的项目?

时间:2018-01-03 23:35:43

标签: ios firebase firebase-realtime-database

我有一个使用包含100,000件商品的Firebase数据库的应用。我的应用程序必须处理这些项目,这需要几秒钟。 发生的事情是,每次启动应用程序(从终止状态),每次都会处理这100,000个项目(即使Firebase服务器上的数据库内容没有更改)。显然,如果没有必要,我不希望应用程序执行此操作。这是一些代码:

if dbRef == nil {
    FirebaseApp.configure();
    Database.database().isPersistenceEnabled = true
    ...
    let dbRef = Database.database().reference(withPath: kFirebaseDBName)
    _ = spamRef.observe(DataEventType.value, with: { (theSnapshot) in
        if let content = theSnapshot.value as? [String : AnyObject]
        {
            self.processContent(content: content)
        }

每次启动应用程序时,内容快照都包含整个数据库引用内容。

有没有办法,例如,获取数据库更新的最后日期(在服务器上),或者只获取每个应用程序启动之间更改的项目的增量 - 查询返回自上次查询后的更改,例如或类似的东西?

我不知道有多少项已更改,因此无法调用以下内容: queryLimited(toLast:N)) 因为我不知道N是什么价值。

我尝试按照以下方式添加keepSynced,希望它可能会改变一些事情,但不会。但是没有。

if dbRef == nil {
    FirebaseApp.configure();
    Database.database().isPersistenceEnabled = true
    ...
    let dbRef = Database.database().reference(withPath: kFirebaseDBName)
    dbRef.keepSynced(true) 
    _ = dbRef.observe(DataEventType.value, with: { (theSnapshot) in
        if let content = theSnapshot.value as? [String : AnyObject]
        {
            self.processContent(content: content)
        }

我不知道有多少数据可能已经改变,因此不知道提供什么价值来提供类似于最后或类似的东西以修改观察参数。 数据库(我没有使用新内容创建或更新)在平面结构中有100,000个项目(即一个父母有100,000个孩子),并且自上次我的应用程序以来,任何数量的这些子项可能已被删除和替换跑了,但总数仍然是10万。没有一个孩子有明确的时间戳或类似的东西。

如果Firebase保留了数据的本地缓存(由于isPersistenceEnabled),那么我的印象是,然后下次与服务器连接时,它只会同步服务器上已更改的内容。因此,为了做到这一点,Firebase本身必须在内部某处有一些delta信息,所以我希望delta信息可以以某种形式提供给我的应用程序。

注意:我的应用需要启用持久性,上面的代码正在这样做,以查看是否有任何事情会导致观察者所希望的行为。

1 个答案:

答案 0 :(得分:1)

<强> 更新

因此,查看documentation以上,您可以设置上次用户使用以下连接到服务器的时间戳:

lastOnlineRef.onDisconnectSetValue(ServerValue.timestamp())

看看this question Frank解释了持久性和听众的一些问题。问题是针对Android,但原则是相同的。

我仍然认为问题是你的查询。由于您已经拥有持久化数据.value不是您想要的,因为这会返回所有数据。

我认为您希望在查询中附加.childChanged侦听器。在这种情况下,查询将仅返回已更改的数据。如果您在阅读.childChanged之前没有听说过keepSynced()here

我没有意识到这个问题与持久性有关。我想你正在寻找ref.child("yourChild").queryLimited(toLast: 7).observeSingleEvent(of: .value, with: { snap in // do something }) 。看看this

原始答案

问题是你的查询。您要求提供所有数据以及获取所有数据的原因。您希望使用toFirst or toLast来限制查询。此外,我不认为您可以查询数据库上次更新的时间。如果您已保存时间戳,则可以检查数据结构中的最后一个节点,但您也可以获取最新数据。

你想要这样的东西:

toLast

根据您编写数据的方式,您需要toFirsttoLast。假设最后写入ref.child("YourChild").queryOrderedByKey().queryEnding(atValue: lastVisiblePostKey).queryLimited(toLast: 8).observeSingleEvent(of: .value, with: { snap in // do something with more posts }) 的最新数据是你想要的。另请注意,我限制使用的数字是任意的,您可以使用任何适合您项目的数字。

如果您已经有一个密钥并且想要在该密钥上方开始查询,则可以执行以下操作:

{
   "Username" : "Pete",
   "Pets" : "Cat",
   "Car" : "Honda Civic",
   "Country" : "Canada"
}

您可能还想查看this questionthis questionpagination