繁体   English   中英

在一个事务中更新多个文档,在多个集合中 Firestore

[英]Update multiple doc, in multiple collection, in one transaction Firestore

这是场景:我需要在 Firestore 中存储排名。 由用户进行排名,每个用户都有一定的积分。

当我存储排名(存储在“匹配”集合中)时,我需要为属于该排名的所有用户更新大量数据、计数器和统计信息。 用户存储在用户集合中,每个用户代表一个文档。

我想在一个事务中这样做,这样如果出现问题,我就没有混合数据(已经更新的东西和没有的东西)。

为此,我考虑遍历排名中的所有用户,并为每个用户读取数据(我需要读取数据,因为我还需要计算平均值)并相应地更新它。 不幸的是,当我读写第一个用户时,在第一个循环中,我无法读取第二个用户,因为在这种情况下,在前一个用户的写入之后会发生新的读取,这是事务禁止的。

您对可能的解决方案有任何线索吗?

@Dharmaraj 我读到了关于批量写入的信息,但据我了解,只有在您不需要从需要写入的文档中读取任何内容时才能使用它们,对吧?

相反,我需要的是,对于排名中的每个用户(因此我的 for 循环中的每个用户)读取他的一些数据(例如在所有比赛中得分的平均分或他的次数在比赛中排名第一)并用我插入的新数据更新这些数据。

例子:

起始情况:

user1 = {
   played_matches: 3
   average_points: 12
   times_in_first_position: 3
}
user2 = {
   played_matches: 2
   average_points: 8
   times_in_first_position: 1
}

新排名:

[
   {username: "user2", points: 2, position: 1}
   {username: "user1", points: 1, position: 2}
]

当我添加一个新的排名时,就像上面片段中的那个,我必须更新“匹配”集合,只需添加这个排名,然后我需要更新用户的数据,如下所示:

user1 = {
   played_matches: 4 (+1)
   average_points: 9,25 (the new average)
   times_in_first_position: 3 (+0)
}
user2 = {
   played_matches: 3 (+1)
   average_points: 6 (the new average)
   times_in_first_position: 2 (+1)
}

这些只是我需要更新的部分数据。 情况要复杂得多,但这是一个很好的近似值。

潜入我当前的代码,我所做的是

for(let user of theSortedUsers){
    if(user.id){
        const userDocRef = doc(db, "users", user.id);
        const userDoc = await transaction.get(userDocRef);
        const newPlayedMatches = parseInt(userDoc.data().played_matches) + 1;
        const newAveragePoints = ((userDoc.data().average_points * userDoc.data().played_matches) + user.points)/ newPlayedMatches;
        transaction.update(userDocRef, { 
              average_points: newAveragePoints,
              played_matches: newPlayedMatches,
        });
    }
}

并且,使用此代码,在处理 user1 之后,用户 2 失败,并出现与所有读取必须在写入之前完成的事实相关的 firestore 错误。

为了进一步解释,我需要做的是这里描述的内容: https://firebase.google.com/docs/firestore/solutions/aggregation但有多个评级和多个餐厅。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM