为什么 Firestore 无法在不同字段上执行具有不等式条件的查询?



我是Firestore数据库的新手,以前没有NoSql数据库的经验(我来自经典的关系数据库(

我知道我可以执行这样的查询:

return this.db.collection(
'courses',
ref=>ref.where("seqNo", "==", "5")
.where("lessonCount", ">=", 5)

这应该检索所有对象(从我的courses集合中(,其中seqNo字段等于5并且lessonCount字段的值>=5

好的,此查询将正常工作。

我不明白的是,为什么在Firebase中无法实现一些简单而自然的查询。例如,经典的范围查询,将上一个查询更改为如下所示:我想检索所有具有seqNo >= 5lessonCount >= 5的课程:

return this.db.collection(
'courses',
ref=>ref.where("seqNo", ">=", "5")
.where("lessonCount", ">=", 5)

我知道这是与性能和指数相关的权衡。

但我不明白为什么 Firestore 无法执行不等式条件没有不同过滤器的查询

为什么?它在引擎盖下是如何工作的?我错过了什么?

我相信有人比我有更全面的解释,但我是这样想的。 Firestore 保证查询在 O(n( 时间内执行,其中 n 是查询中匹配文档的数量。 换句话说,查询根据请求的文档数量进行缩放。 Firestore 的设计目的是在所有(或几乎所有(情况下都如此,并且规模宏(想想集合中的数十亿个文档(。 只要您有支持查询的索引,查询几乎总是表现良好,并且您永远不必担心扩展或分片。 它只是工作。

对字段使用范围查询时,需要对字段使用升序或降序索引。 索引知道集合中所有文档相对于该字段的顺序,并且可以使用该索引有效地查找要匹配的可能文档的范围。但是,当您在另一个字段上引入第二个范围时,这将需要一个完全不同的索引,具有完全不同的潜在范围匹配。这些范围无法合并,在Firestore的大规模下,仍然提供上述性能保证。它必须将可能匹配任一范围的整组文档加载到内存中(或某些临时存储(,找到两者之间的重叠,然后对其应用任何其他过滤器。 想一想 - 出于性能原因,Firestore 根本不愿意将数十亿个文档加载到内存中以查找范围重叠。

这并不是说Firestore根本做不到这一点,但这会大大增加问题的严重性。 如果它提供了多个范围查询,我希望你会为实现这一目标的计算资源付出相当高昂的代价,并且你不会再得到它的原始性能保证。

为了更灵活地查询,您可以将数据镜像到 BigQuery(甚至还有一个扩展(,这将为您提供所需的灵活性。 只是不要指望您的查询速度非常快,并准备好支付 BigQuery 数据仓库功能的成本。

限制为单个范围查询的好处是性能永远不会大规模下降。 缺点是你不能做你想做的一切。 如果你想要一些想法,在Stack Overflow上已经讨论了很多解决方法。

截至 2020 年 10 月,尽管有一些限制,但不平等已经实施到火库。 云恢复现在支持不相等的查询

最新更新