2016-06-26 52 views
1

我对firebase相当陌生,所以我缺乏代码并不缺乏尝试更多的“我不知道从哪里开始”。Firebase查询只返回新帖子?

我试图只显示10分钟“旧”或更少的帖子。我要在我的应用程序中运行一个计时器来每秒发送一次查询(假设这不会导致太多问题?)来检查以确保当前帖子没有超过10分钟标记,并且如果他们是,查询不应该返回它们。

我已经设置了当用户发布时间戳创建的地方。

的设置是:

Posts 
    02983094jfksdflkaj3l 
     timestamp: 23478923019 

我假设我需要orderByValue?按时间戳排序帖子,然后用某种限制返回它,但我不知道如何映射所有这些。

在这里,我们将非常欣赏正确的方向。

在此先感谢!

编辑:我不再收到任何帖子出现在collectionview中...无论我有多少帖子应该满足10分钟以下的查询,只有一个返回。

就像我在下面显示的那样,我没有在snap上得到一个.value返回......它应该返回我在时间戳记打印中显示的timestamp值,不是?

override func viewWillAppear(animated: Bool) { 
    let cutoff = UInt64(1000 * floor(NSDate().timeIntervalSince1970) - 10*60*1000); 
    let cutoffFloat = Float(cutoff) // <-- woudnlt take a UInt64 as an AnyObject. I assume its ok to just do this? 


    DataService.ds.REF_POSTS.queryOrderedByChild("timestamp").queryStartingAtValue(cutoffFloat).observeSingleEventOfType(.ChildAdded) { (snapshot: FIRDataSnapshot) in 
     print("child added") // <------- isn't ever getting called 
     self.Posts = [] 
     if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] { 

      for snap in snapshots { 

      print("timestamp snap: \(snap)") // <---- returns timestamp snap: Snap (timestamp) 23904819242 

         if let postDict = snap.value as? Dictionary<String, AnyObject> { 

        print(snap.value)// <----- Returns nothing 
        let key = snap.key 
        let post = Post(postKey: key, dictionary: postDict) 
        self.Posts.append(post) 

       } 
      } 
     } 

     self.collectionView.reloadData() 

}

我不知道这是否是任何帮助,但这里是我的代码,我用之前填充集合视图:

DataService.ds.REF_POSTS.observeEventType(.Value) { (snapshot: FIRDataSnapshot) in 

     self.Posts = [] 
     if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] { 

      for snap in snapshots { 

       print(snap) 

       if let postDict = snap.value as? Dictionary<String, AnyObject> { 
        let key = snap.key 
        let post = Post(postKey: key, dictionary: postDict) 
        self.Posts.append(post) 
       } 
      } 
     } 

     print("got here") 
     self.collectionView.reloadData() 


    } 
+0

计时器可能是不必要的,您可能要考虑在最后10分钟内有1024个帖子的情况。这些帖子中有多少应该交付给您的客户?我的猜测是,虽然您可能对所有人都感兴趣,但您真的只想每次查看20个或仅查看最近的20个。并且记住Firebase是异步的 - 通过向节点添加观察者到您的应用会自动收到新帖的通知 - 所以它会*总是*显示最新帖子。轮询通常可以通过让Firebase完成工作来完全消除。 – Jay

+0

@Jay 从一群朋友开始,每次只允许向用户显示9个帖子,10分钟的位对我尝试实现的功能很重要。如果没有帖子显示,没关系,因为应用程序的要点是与具有有限数量“展示时间”的帖子进行互动。 如果我只是从用户的朋友的帖子中提取,限制为9,那么不应该存在大量信息或任何问题? 我也只是假设这是最好的方式去做这件事。以这种方式进行讨论会有什么明显的错误吗? – Noowoo

回答

3

运行计时器并每隔10秒发送一个不同的查询是实时数据库的可怕使用。请改为在10分钟前询问所有帖子并保持该查询处于活动状态。

从@ JustinM的代码借鉴:

let ref = FIRDatabase.database().reference 
let cutoff = UInt64(1000 * floor(NSDate().timeIntervalSince1970) - 10*60*1000);  
ref.child("post") 
    .queryOrderedByChild("timestamp") 
    .queryStartingAtValue(cutoff) 
    .observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in 
     let post = Post(title: snapshot["title"], timestamp: snapshot["timestamp"]) 
     self.postsArray.append(post) 
    } 

    self.tableView.reloadData() 

    // start a timer that removes expired items from postsArray 
    NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "removeExpiredItems", userInfo: nil, repeats: true) 
}) 

然后客户端运行定时器,丢弃的职位,因为他们“过期”。

func removeExpiredItems() { 
    let cutoff = UInt64(1000 * floor(NSDate().timeIntervalSince1970) - 10*60*1000) 
    while (self.postsArray.count > 0 && self.postsArray[0].timestamp < cutoff) { 
     // remove first item, because it expired 
     self.postsArray.removeAtIndex(0) 
    } 
    self.tableView.reloadData() 
} 
+0

非常感谢您的帮助。我遇到了一些试图实现这些代码的问题,这些代码是作为原始文章中的修改添加的。你可以看看吗? – Noowoo

+0

谢谢弗兰克。除了评论之外,我没有时间写这篇文章。这绝对是正确的答案。 – Jay

2

这里是你将如何设置运行计时器:

NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector "updateTime", userInfo: nil, repeats: true) 

} 
func updateTime() { 
    let currentTime = NSDate() 
    self.time = currentTime.description 

} 

然后从最近十分钟查询firebase的帖子:

let ref = FIRDatabase.database().reference 
//let x = currentTime - 10 minutes in equivalent time structure. For example, if by minutes, currentTime - 10. You put that in queryStartingAtValue. 
ref.child("post").queryOrderedByChild("timestamp").queryStartingAtValue("x").observeSingleEventOfType(.Value, withBlock: { snapshot in 
     self.postsArray.removeAll 
     for snap in snapshot.children { 
      let post = Post(title: snap["title"], timeStamp: snap["timestamp"]) 
      self.postsArray.append(post) 
     } 

     self.tableView.reloadData() 
    }) 

queryStartingAtValue将为您提供具有您指定的值或更大值的所有帖子。

有一些更好的方法可以处理这一点,但这应该是一个好的开始,新的Firebase有一些很棒的文档和示例。查看他们关于数据库/检索数据的部分,了解更多关于排序/过滤的内容

希望这可以帮助你入门,让我知道如果您有任何问题。

+0

呃。此查询将无法正常工作,因为它:.Child添加将一次捕获一个子节点,因此快照中只会有一个子节点,从而否定迭代快照以获取其他帖子。它也将在每次通话后清空阵列,以便您最终得到一篇文章。此外,它可能会导致表闪烁,好像有1000个帖子,它会连续更新1000次tableView。另外,如果x =上午9点,所有帖子都会添加观察员:8点50分到9点。然后,如果它在9:10再次运行,它将在上午8点50分到上午9点的帖子之后为从9:10到9的所有内容添加更多观察者。 – Jay

+0

那么你认为最好的是什么? observeSingleEventOfType(.value的)? – JustinM

+0

是的,如果OP使用定时器,这是一个好的开始。但是,如果是这种情况,那真的会给应用增加很多开销,并且会击败Firebase的目的。同样,如果该计时器每秒钟都会触发,它可能会推送大量的数据,并且会导致“回调地狱”问题,因为数据在最后一次数据处理之前正在返回。数据流的背后思考过程以及它如何呈现应该可能被重新访问。 – Jay