假设聊天应用程序具有1000万Firebase用户和数亿条消息。
我有一个Firestore集合,其中包含以时间序列表示为文档的消息,并且这些消息中的每一个都可以被多达100个这些用户接收和查看。请注意,这些用户不是按稳定的组进行组织的,因为每条消息可能都有一组完全不同的接收消息的用户。
我需要能够非常有效地(在时间和成本方面)找到 在特定时间后将所有消息定向到特定用户。
我的第一个失败尝试是在recipients
数组字段中列出收件人用户,例如:
sender: user3567381
dateTime : 2019-01-24T20:37:28Z
recipients : [user1033029, user9273842, user8293413, user6273581]
但是,那将不允许我高效地查询。
作为second failed attempt,由于Firestore是无模式的,所以我想到了使每个用户成为一个字段,如下所示:
sender: user3567381
dateTime : 2019-01-24T20:37:28Z
user1033029 : true
user9273842 : true
user8293413 : true
user6273581 : true
然后,例如,如果我想在今天3:00 PM之后知道用户8993413的所有消息,我可以这样进行:
messages.where("user8293413", "==", true).where("dateTime", ">=", "2019-01-24T15:00:00Z")
这是一个复合索引查询,每个用户需要一个索引。不幸的是,每个数据库的限制为200 composite-indexes。
要解决此问题,我目前的尝试是将日期转换为用户字段的值,如下所示:
sender: user3567381
dateTime : 2019-01-24T20:37:28Z
user1033029 : 2019-01-24T20:37:28Z
user9273842 : 2019-01-24T20:37:28Z
user8293413 : 2019-01-24T20:37:28Z
user6273581 : 2019-01-24T20:37:28Z
现在,如果我想在今天3:00 PM之后知道用户8993413的所有消息,我可以这样做:
messages.where("user8293413", ">=", "2019-01-24T15:00:00Z")
请注意,这现在是 单字段索引 。
从文档中我知道Firestore将为所有字段创建单字段索引,因此这意味着它将为user8293413特别创建索引。 这意味着搜索将很快,对吗?并且将读取次数保持为最少(每条消息读取一次)。
但是,由于我有1000万用户,因此 Firestore必须为整个数据库创建1000万个单字段索引(假设所有用户都收到消息)。
在documentation Firestore中有以下限制:
通过阅读以上内容,这些引起了我的注意:
但是,他们声明限制是每个文档,而不是每个数据库。而且我只有数百万个数据库索引,没有每个文档。
有问题吗?这么多索引会影响性能吗?所有这些索引的存储成本如何?是否为每个数据库中的大量索引准备了Firebase?
答案 0 :(得分:0)
尽管几个月后,对于任何将来的用户来说,似乎第一次尝试都可能是最好的。
对时间戳使用单个静态字段,对收件人使用单个静态字段,则索引将保持可忽略不计,而您不必考虑它们。
要查找用户的所有消息,这似乎是您的目标:
例如,如果我想在之后知道用户8293413的所有消息 今天下午3:00,我可以这样做:
在伪代码中,它看起来像这样:
firestore.collection('messages').where('recipient', 'array_contains', userId).where('time', '>', '3pm today'.get()
这应该在性能上足够简单,Firebase已针对其提供的运营商进行了优化,例如'==','> =','array_contains'