我正在尝试更新Firestore中文档中的字段。该文档的一般位置为“ / games / {userId} / userGames / {gameId}。在此游戏中,有一个名为“ status”的属性,该属性会根据游戏的开始和结束时间而改变。
您可以猜测,如果开始时间大于“现在”时间戳,并且状态为“ TO_BE_PLAYED ”,则游戏将开始,状态为1,“ BEING_PLAYED ”。另外,如果结束时间大于“现在”时间戳,并且状态为“ BEING_PLAYED ”,则游戏将结束,因此状态为2,即“ PLAYED ” ”。我想创建一个能够做到这一点的云功能。
但是,即使函数日志输出为“ ok”,该值也不会更新。不幸的是,我也没有太多的Java经验。
代码
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const STATUS_PLAYED = 2;
const STATUS_BEING_PLAYED = 1;
const STATUS_TO_BE_PLAYED = 0;
exports.handleBeingPlayedGames = functions.runWith({memory: "2GB"}).pubsub.schedule('* * * * *')
.timeZone('Europe/Istanbul') // Users can choose timezone - default is America/Los_Angeles
.onRun(async () => {
// current time & stable
// was Timestamp.now();
const now = admin.firestore.Timestamp.fromDate( new Date());
const querySnapshot = await db.collection("games").get();
const promises = [];
querySnapshot.forEach( doc => {
const docRef = doc.ref;
console.log(docRef);
promises.push(docRef.collection("userGames").where("status", "==", STATUS_BEING_PLAYED).where("endtime", "<", now).get());
});
const snapshotArrays = await Promise.all(promises);
const promises1 = [];
snapshotArrays.forEach( snapArray => {
snapArray.forEach(snap => {
promises1.push(snap.ref.update({
"status": STATUS_PLAYED,
}));
});
});
return Promise.all(promises1);
});
exports.handleToBePlayedGames = functions.runWith({memory: "2GB"}).pubsub.schedule('* * * * *')
.onRun(async () => {
// current time & stable
// was Timestamp.now();
const now = admin.firestore.Timestamp.fromDate(new Date());
const querySnapshot = await db.collection("games").get();
const promises = [];
querySnapshot.forEach( async doc => {
const docData = await doc.ref.collection("userGames").where("status", "==", STATUS_TO_BE_PLAYED).where("startTime", ">", now).get();
promises.push(docData);
});
const snapshotArrays = await Promise.all(promises);
const promises1 = [];
snapshotArrays.forEach( snapArray => {
snapArray.forEach(snap => {
promises1.push(snap.ref.update({
"status": STATUS_BEING_PLAYED,
}));
});
});
return Promise.all(promises1);
});
答案 0 :(得分:1)
好的,所以这个答案适用于试图解决这个问题的潜伏者。
首先,我尝试通过蛮力解决这个问题,但不花很多心思,并试图从子集合中获取价值。但是,在搜索时,我发现对数据进行非规范化(扁平化)实际上可以解决该问题。
我在/status/{gameId}
下使用属性创建了一个新目录
endTime, startTime, and status field
,实际上我是通过使用诺言在单个级别上完成的。有时,对数据进行非规范化可能是您的救星。
答案 1 :(得分:0)
startTime
如何大于now
?默认情况下是否将其设置为将来的日期?
我目前的假设是,由于与STATUS_BEING_PLAYED
不一致,因此游戏无法将其状态设置为startTime
。此外,游戏不能具有状态STATUS_PLAYED
,因为它取决于拥有STATUS_BEING_PLAYED
,而状态startTime
却不能拥有。
我的建议是将字段endTime
和null
缺省设置为STATUS_BEING_PLAYED
。如果这样做,您可以使用以下方法检查是否必须将游戏设置为doc.ref.collection("userGames")
.where("status", "==", STATUS_TO_BE_PLAYED)
.where("startTime", "<", now)
.where("endTime", "==", null)
.get();
:
STATUS_PLAYED
您可以以此来检查游戏是否必须在docRef.collection("userGames")
.where("status", "==", STATUS_BEING_PLAYED)
.where("endtime", "<", now)
.get();
上进行(完全一样):
==
现在,您应该怀疑,这是更改游戏状态的最佳方法吗?如您所知read operations are charged,您正在查询用户的整个游戏库每分钟,因此这种方法将产生有意义的费用。也许您应该只在游戏启动和关闭时使用更新游戏的状态即可。
还要注意,等于操作是=
,而不是+
。