我有一个带有 users 集合的Firestore数据库。每个用户都是一个包含联系人集合的文档。该集合中的每个文档都是一个联系人。
由于firestore没有所有文档的“计数”功能,并且由于我不想读取所有联系人以计算用户拥有的联系人数量,因此当添加或删除了联系人,从而在用户文档中增加或减少了 numberOfContacts 。为了使该函数幂等,它必须执行多次读取和写入操作,以防止在同一文档中多次调用该计数器时增加计数器一次。这意味着我需要拥有一个已经处理过的不同的eventID集合,因此我不会重复它。这就要求我每月运行一次另一个功能,以使每个用户删除所有此类文档(其中包括很多读取和某些写入)。
现在的挑战是用户可以导入他/她的联系人。因此,如果用户导入10,000个联系人,此功能将快速连续触发10,000次。
如何预防?
现在,我正在联系文档中添加一个字段,指示该添加是导入的一部分。这使云功能不增加。
我在一次交易中一次从客户端499联系人执行操作,这也随着第500次写入而增加计数。这样,如果中途失败,计数将保持一致。
这真的是最好的方法吗?仅提供大量联系人似乎太复杂了。每次更改单个联系人后,我都要进行多次读写操作,而且我每个月都必须运行清除功能。
我一直认为必须有一种更简单的方法。
答案 0 :(得分:0)
对于那些好奇的人,看来我采用的方法是最好的方法。
我在联系文档中添加了一个字段,指示该添加是导入的一部分(bulkAdd = true)。这将使云功能不增加。
我还有另一个云功能,一次添加联系人200(我执行FieldValue.timestamp,这算作另一个写入,因此是400次写入)。我分批执行此操作,并且批处理中的第401个写入是增量计数。这样,我就可以批量导入联系人,而不必用写入轰炸单个文档。
答案 1 :(得分:0)
递增问题
有重复安全操作,例如FieldValue.arrayUnion()
和FieldValue.arrayRemove()
。我在这里写了一些关于这种方法的内容:Firebase function document.create and user.create triggers firing multiple times
通过这种方法,您可以使用户文档包含带有联系人ID的特殊数组字段。将联系人添加到子集合并触发您的功能后,可以将联系人的ID写入此字段。如果某个联系人两次或多次触发该功能,则只有一个实例写入主用户文档。但是实际大小可以在客户端获取,也可以在用户文档更新中触发其他功能。这比具有eventID更为简单。
导入超过1万个联系人的问题
从哲学上讲,这有点。 如果我明白了,问题是用户执行了1万次写入。比这10k次写入触发10k函数,这些功能会对主文档执行额外的10k次写入(如果使用eventIDs文档,则执行相同的读取次数)?
您可以创建一个特殊的子集合,仅用于将多个联系人导入数据库。客户端无需向数据库编写10k文档,而是创建一个包含10k联系人字段的大型文档,从而触发云功能。提到的函数将全部读取,并与所有arrayUnions进行必要的10k联系人写入+1写到主文档。您只需要考虑如何防止10k调用的函数写入(添加像您的bulkAdd这样的特殊元数据字段)
这只是一种意见。