Firebase Cloud Functions-如何在事务或批处理写入中更新子集合文档?

时间:2018-06-21 17:48:34

标签: node.js firebase google-cloud-firestore google-cloud-functions

我正在尝试创建一个排名,在该排名中,将为每个对象分配一组描述其排名的属性(适用于多次读取和少量写入)。

这是我创建的:

exports.calculateRanking = functions.firestore.document('players/{playerId}').onUpdate((change, context) => {

if (typeof change.before.data().score === 'undefined' && change.after.data().score > 0) {

    var db = admin.firestore();
    var batch = db.batch();
    return db.collection("players").orderBy("score", "desc").get().then(snapshot => {
            var docs = snapshot.docs;
            var map = {};
            for (var i = 0; i < docs.length; i++){
                var player = docs[i];

                var position = i + 1;
                var industry = player.industry;
                var age = player.age;

                if (map[industry] !== null){
                    map[industry] += 1;
                }
                else{
                    map[industry] = 1;
                }

                if (map[age] !== null){
                    map[age] += 1;
                }
                else{
                    map[age] = 1;
                }

                if (map[industry+age] !== null){
                    map[industry+age] += 1;
                }
                else{
                    map[industry+age] = 1;
                }

                console.log(player.name);

                return player.ref.collection("rankings").get().then(rankings => {
                    return rankings.docs.forEach(ranking => {

                        console.log("Inside ranking loop");

                        var currGeneralRanking = ranking.data().generalRanking.curr;
                        var currIndustryRanking = ranking.data().industryRanking.curr;
                        var currAgeRanking = ranking.data().ageRanking.curr;
                        var currIndustryAgeRanking = ranking.data().industryAgeRanking.curr;

                        var newGeneralRanking = position;
                        var newIndustryRanking = map[industry];
                        var newAgeRanking = map[age];
                        var newIndustryAgeRanking = map[industry+age];

                        var newCurrGeneral;
                        var newCurrIndustry;
                        var newCurrAge;
                        var newCurrIndustryAge;

                        var newPrevGeneral;
                        var newPrevIndustry;
                        var newPrevAge;
                        var newPrevIndustryAge;

                        if (currGeneralRanking !== 0){
                            if (newGeneralRanking !== currGeneralRanking){
                                newPrevGeneral = currGeneralRanking;
                            }
                            else{
                                newPrevGeneral = ranking.data().ranking.prev; 
                            }   
                        }
                        else {
                            newPrevGeneral = newGeneralRanking;
                        }

                        newCurrGeneral = newGeneralRanking;

                        if (currIndustryRanking !== 0){
                            if (newIndustryRanking !== currIndustryRanking){
                                newPrevIndustry = currIndustryRanking;
                            }
                            else{
                                newPrevIndustry = ranking.data().industryRanking.prev;    
                            }
                        }
                        else{
                            newPrevIndustry = newIndustryRanking;
                        }

                        newCurrIndustry = newIndustryRanking;

                        if (currAgeRanking !== 0) {
                            if (newAgeRanking !== currAgeRanking) {
                                newPrevAge = currAgeRanking;
                            }
                            else{
                                newPrevAge = ranking.data().ageRanking.prev;
                            }
                        }
                        else{
                            newPrevAge = newAgeRanking;
                        } 

                        newCurrAge = newAgeRanking;  

                        if (currIndustryAgeRanking !== 0) {
                            if (newIndustryAgeRanking === currAgeIndustryRanking){
                                newPrevIndustryAge = currAgeIndustryRanking;
                            }
                            else{
                                newPrevIndustryAge = ranking.data().industryAgeRanking.prev;
                            }
                        }
                        else{
                            newPrevIndustryAge = newIndustryAgeRanking;
                        }

                        newCurrIndustryAge = newIndustryAgeRanking;

                        return batch.update(ranking.ref, { 
                            "generalRanking": { 
                                "curr": newCurrGeneral,
                                "prev": newPrevGeneral
                            },
                            "industryRanking": {
                                "curr": newCurrIndustry,
                                "prev": newPrevIndustry
                            },
                            "ageRanking": {
                                "curr": newCurrAge,
                                "prev": newPrevAge
                            },
                            "industryAgeRanking": {
                                "curr": newCurrIndustryAge,
                                "prev": newPrevIndustryAge
                            } 
                        });
                    });
                }).catch(error => {
                    return console.log(error);
                });
            }
            return batch.commit().then(result => {
                return console.log(result);
            }).catch(error => {
                return console.log(error);
            });
    }).then(result => {
        return console.log('Transaction success', result);
    }).catch(err => {
        return console.log('Transaction failure:', err);
    });   
}    

return;
});

虽然循环只运行一次。似乎(很明显)循环内的返回中断了它。

那么如何做出承诺?我正在考虑对一系列Promise.all()的承诺进行ranking的交易。然后问题就变成了从map到每个ranking集合的位置匹配。这样可以使map映射到字典/哈希图,并且每个键对应于每个玩家的ID。不过,在集合ranking中创建文档仅同时映射到玩家的ID也很糟糕。

所以,我的问题是,如果确实是只有Promise.all()才能解决循环问题,我如何制作每个ranking集合,将其输出到下一个Promise的then(rankings =>会很好地知道它属于哪个玩家

0 个答案:

没有答案