简体   繁体   English

如何跳过初始数据并仅触发 Firestore Firebase 中的新更新?

[英]How to skip initial data and trigger only new updates in Firestore Firebase?

I've searched everywhere with no luck.我到处搜索都没有运气。 I want to query Firestore to get all users WHERE type is admin.我想查询 Firestore 以获取类型为管理员的所有用户。 Something like:就像是:

SELECT * FROM users WHERE type=admin

but only when the property total is changing.当财产total发生变化时。 If I'm using:如果我使用:

users.whereEqualTo("type", "admin").addSnapshotListener(new EventListener<QuerySnapshot>() {
    @Override
    public void onEvent(@Nullable QuerySnapshot snapshots, @Nullable FirebaseFirestoreException e) {
        for (DocumentChange dc : snapshots.getDocumentChanges()) {
            switch (dc.getType()) {
                case ADDED:
                    //Not trigger
                    break;
                case MODIFIED:
                    //Trigger
                    break;
                case REMOVED:
                    //
                    break;
            }
        }
    }
});

The case ADDED is triggered first time when I query and when the total is changed case MODIFIED is triggered again (this is what is want).当我查询时第一次触发案例 ADDED 并且当total更改时case MODIFIED再次触发(这就是想要的)。 I want only changes and not the all initial data, I don't need it.我只想要更改而不是所有初始数据,我不需要它。 How to get it?如何获得?

Please help me, is the last part of my project.请帮助我,这是我项目的最后一部分。 How to skip is case ADDED ?如何跳过添加的case ADDED

When you are listening for changes in Cloud Firestore for realtime changes, using Firestore Query's addSnapshotListener() method, it:当您在 Cloud Firestore 中监听实时更改时,使用 Firestore Query 的addSnapshotListener()方法,它:

Starts listening to this query.开始侦听此查询。

Which basically means that first time you attach the listener, you get all documents that correspond to that particular query.这基本上意味着第一次附加侦听器时,您将获得与该特定查询相对应的所有文档。 Furthermore, everytime a property within a document changes, you are notified according to that change.此外,每次文档中的属性发生更改时,您都会根据该更改收到通知。 Obviously, this is happening only if the listener remains active and is not removed.显然,只有当侦听器保持活动状态并且未被移除时才会发生这种情况。

Unfortunately, Firestore listeners don't work that way, so you cannot skip that "case ADDED".不幸的是,Firestore 侦听器不会以这种方式工作,因此您不能跳过“case ADDED”。 What you can do instead, is to add add under each user object a Date property ( this is how you can add it) and query your database on client, according to this new property, for all documents that have changed since a previous time.相反,您可以做的是在每个用户对象下添加一个Date属性( 是您添加它的方式),并根据此新属性在客户端查询您的数据库,以查找自上次以来已更改的所有文档。

According to Nick Cardoso's comment, for future visitors that might ask why this behaviour happens, is because the reason he mentioned in his comment.根据 Nick Cardoso 的评论,对于未来可能会问为什么会发生这种行为的访客,是因为他在评论中提到的原因。 I also recommend see Doug Stevenson's answer from this post , for a better understanding.我还建议从这篇文章中查看 Doug Stevenson 的回答,以便更好地理解。

有一个选项可以检查 querySnapshot 是否来自缓存,更改返回 false

if(querySnapshot.getMetadata().isFromCache()) return

Here is a solution working for me: use这是一个对我有用的解决方案:使用

AtomicBoolean isFirstListener = new AtomicBoolean(true);

and then on event method然后在事件方法上

if (isFirstListener.get()) {
                    isFirstListener.set(false);
                    //TODO Handle the entire list. 
                    return;
                }

Here is a sample code from my project:这是我的项目中的示例代码:

 final AtomicBoolean isFirstListener = new AtomicBoolean(true);
 mDb.collection("conversation_log").document(room_id).collection("messages").orderBy("sent_at")
    .addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@Nullable QuerySnapshot value2, @Nullable FirebaseFirestoreException e) {
        if (isFirstListener.get()) {
            isFirstListener.set(false);
            //TODO Handle the entire list.
            return;
        }
    }
});

reference: answer参考:答案

Found a work around for this given use case, it is possible to skip the initial data and get only updates.找到了解决这个给定用例的方法,可以跳过初始数据并仅获取更新。 The workaround is including a server timestamp in your structure and build your query to fetch only the data that has timestamp greater than the current time.解决方法是在您的结构中包含一个服务器时间戳,并构建您的查询以仅获取时间戳大于当前时间的数据。

val ref = db.collection("Messages").document("Client_ID")
        .collection("Private")
        .orderBy("timestamp")
        .whereGreaterThan("timestamp",Calendar.getInstance().time)

//Add snapshot listener
ref.addSnapshotListener { snapshot , e ->
            if (snapshot != null) {
                Log.d("TAG", "Current data: ${snapshot.documents.size}")
                for(document in snapshot.documents){
                    Log.e("Document Data",document.data.toString())
                }
            }
        }

So, the query won't return any data in the initial build, but will listen to the document changes.因此,查询不会在初始构建中返回任何数据,但会监听文档更改。 As soon as timestamp of a document changes, you'll be notified about that change.一旦文档的时间戳发生变化,您就会收到有关该变化的通知。 Then you can check if the data exists in your list (if you're looking for modifications, or if it's a new document added)然后你可以检查数据是否存在于你的列表中(如果你正在寻找修改,或者它是否是添加的新文档)

Just update timestamp of the document when your write any changes.当您写入任何更改时,只需更新文档的时间戳。 As shown below:如下所示:

val message = hashMapOf<String,Any>(
        "timestamp" to FieldValue.serverTimestamp(),
        "id" to userId,
        "data" to data,
    )
db.collection("Messages").document("Client_ID")
        .collection("Private")
        .document().set(message)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM