Firestore - 在本地合并两个查询

Posted

技术标签:

【中文标题】Firestore - 在本地合并两个查询【英文标题】:Firestore - Merging two queries locally 【发布时间】:2018-10-11 14:26:07 【问题描述】:

由于 Firestore 中没有逻辑 OR 运算符,我试图在本地合并 2 个单独的查询。

现在我想知道如何才能保持结果的正确顺序。当我独立运行 2 个查询时,我无法对结果进行具体排序(至少不是我使用 orderBy 方法从 Firestore 获取结果的顺序)。

我的想法是将第二个查询放在第一个查询的 onSuccessListener 中。这是一个坏主意吗?

public void loadNotes(View v) 
    collectionRef.whereLessThan("priority", 2)
            .orderBy("priority")
            .get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() 
                @Override
                public void onSuccess(QuerySnapshot queryDocumentSnapshots) 

                    for (QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots) 
                        Note note = documentSnapshot.toObject(Note.class);
                        //adding the results to a List
                    

                    collectionRef.whereGreaterThan("priority", 2)
                            .orderBy("priority")
                            .get()
                            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() 
                                @Override
                                public void onSuccess(QuerySnapshot queryDocumentSnapshots) 

                                    for (QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots) 
                                        Note note = documentSnapshot.toObject(Note.class);
                                        //adding the results to a List
                                    
                                
                            );
                
            );

【问题讨论】:

【参考方案1】:

要在本地合并 2 个单独的查询,我建议您使用 Tasks.whenAllSuccess() 方法。您可以使用以下代码行来实现这一点:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query firstQuery = rootRef...
Query secondQuery = rootRef...

Task firstTask = firstQuery.get();
Task secondTask = secondQuery.get();

Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() 
    @Override
    public void onSuccess(List<Object> list) 
         //Do what you need to do with your list
    
);

如您所见,当覆盖onSuccess() 方法时,结果是对象的list,其具有作为参数传递给whenAllSuccess() 方法的任务的确切顺序。

还有另一种方法,那就是使用Tasks.continueWith() 方法。但是根据您的应用程序的用例,您可以使用eiter whenAllSuccess() 方法或continueWith() 方法。请在此处查看official documentation。

【讨论】:

非常感谢!我实际上在网上找到了相同的解决方案,但如果它们是正确的,我会非常不安全,因为我发现的例子太少了。既然你命名了完全相同的方法,我就有了保险。一件事:我是一个新手,所以我对泛型有问题,但我注意到当我写Task&lt;List&lt;QuerySnapshot&gt;&gt; combinedTask而不是像Task那样声明类型时,我在OnSucess中得到一个List&lt;QuerySnapshot&gt;,而不是List&lt;Object , 这样更方便。这是声明类型的正确方法吗? QuerySnapshot 类,就像 Java 中的所有其他类一样,扩展了 Object 类。类对象是类层次结构的根。每个类都有 Object 作为超类。所以QuerySnapshot 是一个对象。在这种情况下,QuerySnapshot 是相关类型,因此请随意使用List&lt;QuerySnapshot&gt; 好的,但这比在onSuccess 中转换objects 更好还是没关系? @fkvestak 您将总是承担与返回的元素数量相等的读取操作数。例如,如果您有 3 个查询,并且每个查询都返回 3 个文档,那么您将被收取 9 次文档读取的费用。 @fkvestak 我认为article 将提供更多信息。真的不是你说的那样。

以上是关于Firestore - 在本地合并两个查询的主要内容,如果未能解决你的问题,请参考以下文章

在 Firestore REST API 中查询嵌套对象

合并 Firestore 查询时出现重复数据

如何从 firestore 两个集合中获取数据并将所有数据合并在一起

使用 rxDart 合并 Firestore 流

我可以通过 GeoPoint 值查询 Firestore 数据库以查找本地位置吗?

Firestore:如果两个侦听器监听相同的查询 firebase 维护两个不同的查询快照?