【问题标题】:Firebase Query Or'ing whereEqualTo for a list of possible valuesFirebase 查询 Or'ing whereEqualTo 以获取可能值的列表
【发布时间】:2018-12-22 05:53:41
【问题描述】:

我看到 this question before for an earlier version of Firebase 不再适用于 Firebase Cloud Firestore。

我想做一个查询,根据潜在值列表检查文档字段的值,例如whereEqualTo(someField, a OR b OR c OR ... OR n)。具体来说,我有一个 Reference 类型的单个字段的潜在值列表,我希望我的查询返回指定集合中的所有文档,其字段的值等于列表中的潜在值之一。我也在使用.limit(10),因为我正在对数据进行分页。

例如,如果我的列表包含引用 [ref1, ref2, ref3] 那么查询将类似于加入这 3 个查询:

查询 query1 = mDatabase.collection("myCollection").whereEqualTo("refField", ref1);
查询 query2 = mDatabase.collection("myCollection").whereEqualTo("refField", ref2);
查询 query3 = mDatabase.collection("myCollection").whereEqualTo("refField", ref3);

documentation 的“限制”部分下,它提到:

Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.

所以也许最好的方法是合并查询结果,但如何做到这一点,并且限制为 10 个结果?

请注意,我正在使用 Java 进行 Android 开发。

【问题讨论】:

    标签: java android firebase google-cloud-firestore


    【解决方案1】:

    我想做一个查询,根据潜在值列表检查文档字段的值。

    很遗憾,Firestore 中没有任何查询可以帮助您实现这一目标。相反,您可以做的是获取 myCollection 集合下的所有文档,并根据可能的值列表检查您需要的文档字段的值,如下所示:

    FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
    CollectionReference myCollectionRef = rootRef.collection("myCollection");
    myCollectionRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                List<String> yourList = new ArrayList<>();
                for (QueryDocumentSnapshot document : task.getResult()) {
                    DocumentReference reference = document.getDocumentReference("refField");
                    String stringReference = reference.getPath();
                    if (yourList.contains(stringReference)) {
                        Log.d(TAG, "Reference found!");
                    }
                }
            }
        }
    });
    

    我假设您的列表包含字符串类型的文档引用。如您所见,我们需要序列化我们从数据库中获取的DocumentReference 对象,使用getPath() 方法获取描述文档在数据库中的位置的字符串。要将路径字符串反序列化回DocumentReference 对象,请使用FirebaseFirestore.getInstance().document(path) 方法。

    PS。如果您对分页感兴趣,this 是您可以通过将查询游标与 limit() 方法相结合来对查询进行分页的方法。我还建议您看看这个 video 以获得更好的理解。

    【讨论】:

    • 我遇到的问题是它会获取并循环遍历集合中的每个文档。因此,如果集合中有大量文档不包含其中一个引用,那么在第一个包含其中一个引用的文档之前,它可能需要很长时间才能找到引用。它基本上是 O(n),如果 n 是文档的数量很大,这会很慢,违背了使用查询的目的。添加分页,每次获取更多文档时,分页都会成倍增加。
    • 这是不正确的。上面的代码只是一个例子。如果您使用分页,正如您所说的那样,您不会查询整个数据库,您将使用 limit() 方法来帮助您防止这种情况。这就是为什么您使用分页以较小的块加载数据的原因。即使您想查询整个数据库,请记住 Firestore 会自动扩展,对吗?见here
    • 还有一点需要注意,其中一位 Firebase 工程师说,我引用了一句,“在 Firestore 中构建慢查询是不可能的”。因此,性能来自新的索引功能。所以不用担心可扩展性。
    • 即使我使用 limit(10) 方法,如果有 1000 个文档并且只有最后一个有参考,我需要进行 100 次查询,每个循环遍历所有 10 个文档在我到达带有参考的文件之前的时间。 Firestore 的索引功能无济于事,因为它不知道我正在寻找客户端上的特定参考,对吧?因此,尽管获取每 10 个文档并不是一个“慢”查询,但它仍然很慢,因为它必须执行 100 次并在客户端上循环遍历每 10 个。因此,最坏情况的运行时间与我获取每个文档相同。
    • 它这么慢的原因是因为它没有限制在查询期间获取的文档(我正在尝试这样做)通过 whereEqualTo 或类似的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 2016-04-05
    • 2017-06-16
    相关资源
    最近更新 更多