已添加Firebase子项\u仅获取已添加的子项

已添加Firebase子项\u仅获取已添加的子项,firebase,Firebase,从Firebase API: 添加的子项:此事件将为每个初始子项触发一次 在该位置,每次新的 添加了child 一些代码: listRef.on('child_added', function(childSnapshot, prevChildName) { // do something with the child }); 但是,由于此位置的每个子项都会调用一次函数,因此有没有办法只获取实际添加的子项?要跟踪自某个检查点以来添加的内容而不获取以前的记录,可以使用endAt()和lim

从Firebase API:

添加的子项:此事件将为每个初始子项触发一次 在该位置,每次新的 添加了child

一些代码:

listRef.on('child_added', function(childSnapshot, prevChildName) {
    // do something with the child
});

但是,由于此位置的每个子项都会调用一次函数,因此有没有办法只获取实际添加的子项?

要跟踪自某个检查点以来添加的内容而不获取以前的记录,可以使用
endAt()
limit()
获取最后一条记录:

// retrieve the last record from `ref`
ref.endAt().limitToLast(1).on('child_added', function(snapshot) {

   // all records after the last continue to invoke this function
   console.log(snapshot.name(), snapshot.val());

});
limit()
方法已弃用
limitToLast()
limitToFirst()
方法替换它

// retrieve the last record from `ref`
ref.limitToLast(1).on('child_added', function(snapshot) {

   // all records after the last continue to invoke this function
   console.log(snapshot.name(), snapshot.val());
   // get the last inserted key
   console.log(snapshot.key());

});
Swift3解决方案:

您可以通过以下代码检索以前的数据:

    queryRef?.observeSingleEvent(of: .value, with: { (snapshot) in
        //Your code

    })
然后通过以下代码观察新数据

queryRef?.queryLimited(toLast: 1).observe(.childAdded, with: { (snapshot) in

 //Your Code

        })

我尝试了其他的答案,但最后一个孩子至少用了一次。如果您的数据中有一个时间键,您可以这样做

ref.orderByChild('createdAt').startAt(Date.now()).on('child_added', ...

由于在没有数据的情况下调用
ref.push()
方法会根据时间生成路径键,因此我就是这样做的:

// Get your base reference
const messagesRef = firebase.database().ref().child("messages");

// Get a firebase generated key, based on current time
const startKey = messagesRef.push().key;

// 'startAt' this key, equivalent to 'start from the present second'
messagesRef.orderByKey().startAt(startKey)
.on("child_added", 
    (snapshot)=>{ /*Do something with future children*/}
);
请注意,
ref.push()
返回的引用(或“键”)实际上没有写入任何内容,因此不需要捕获空数据

由于
.limitToLast()
方法仍然为列表中的最后一项调用,即使它不是新项,我们可以按如下方式解决它:

想法是:

创建保存firebase项目的列表;每当调用
onchildaded(…)
方法时,检查传入的datasnapshot是否在列表中;如果不是,则是新数据

为了实现这一点,您必须满足以下条件:

  • 每个项目都有一个唯一的值。(这可以通过使用
    .push()
    方法生成的键将项目添加到Firebase中来实现

  • 重写模型类的
    .equals()
    方法,以便基于此唯一值进行比较

  • 代码片段

    注意:我选择将项目列表放在模型类中

    模型类

    public class MyModel {
    
        private String id; // unique ID from model to another
        public static List<MyModel> sItems; // my tracked items
    
        // reset of fields ...
    
    
        public MyModel() {
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
    
        @Override
        public boolean equals(@Nullable Object o) {
    
            // If the object is compared with itself then return true
            if (o == this) {
                return true;
            }
    
            // Check if o is an instance of MyModel or not
            if (!(o instanceof MyModel)) {
                return false;
            }
    
            // typecast o to MyModel so that we can compare data members
            MyModel model = (MyModel) o;
    
            // Compare data based on the unique id
            return (model.id).equals(id);
        }
    
    }
    
    然后限制到最后

    databaseReference.limitToLast(1).addChildEventListener(mChildEventListener);
    

    事实上,我发现了一种更简单的方法,因为即使在达到limit()之后,它也会继续通知您添加的事件。我已经相应地更新了我的答案。不清楚您的意思。这只适用于有序集,但如果您需要为其他内容(除了有序集之外)排序,它会起作用…此外,您的注释也不能帮助任何人理解如何在Firebase中获取子添加事件。回调函数仅对
    ref.endAt().limit(1)返回的记录激发一次
    。它不会为在该记录之后添加的其他新记录触发。我正在使用Angularfire 0.8.0Kato对GitHub进行测试。它对最后一个子项(在添加新子项之前)仍会调用回调一次,对吗?我尝试过这种方法,但有一件事需要注意:如果最后一条记录被删除,例如,用户发布一条评论并立即删除(例如,这是一个错误),请参见上面的函数将被再次调用。我解决了添加时间戳并检查所添加的子项是否小于1秒,如果较旧,则为旧记录且未添加。为此,请查看ref.child('.info')我不了解它-这不就是最后一项吗?关于“仅在绑定到此事件后添加的项”如何?是的,我也这么想。它只获取最后一条消息一次,然后就不会为其他添加的事件触发。@DivZero我试着按照你说的做,但由于我的聊天在android和iOS之间共享,所以无法工作,因为来自其他设备的消息延迟较长。它也容易出错,所以我检查了新消息是否已经在聊天中,我如果是,我不添加它。
    child_added
    函数采用两个参数,
    snapshot
    prevChildKey
    ,这种方法
    prevChildKey
    总是空的。我使用了
    ref.endAt().on('child_added',function(snapshot,prev){})
    为什么这个方法不按照它说的那样做呢?它应该只做一件事——在添加孩子时触发——别的什么都不做。是的,同意@jose Browne。它让人困惑…[2018-04-27T23:58:32.727Z]@ FialBase/Dave:FielBase警告:使用未指定的索引。您的数据将在客户端上下载和筛选。考虑添加“.index”:“CealDATA”。at/sms记录到您的安全规则中以获得更好的性能。您能否在此基础上进行扩展,以便.childAdded不会添加所有消息。因此,如果我使用的是数组,我希望在observeSingleEvent中查询最后100个,然后在之后侦听.chlidded和.childRemoved中的所有新事件。如果我正确理解您的问题,您希望检索吗在开始的最后100条记录,然后你想要监听更新。基于谷歌文档,你可以使用“queryLimitedToLast”观察者。
    databaseReference.limitToLast(1).addChildEventListener(mChildEventListener);