Firestore简单排行榜功能

时间:2018-11-06 17:31:13

标签: javascript firebase google-cloud-firestore

我正在尝试编写一个云函数,该函数将我的用户按/ eared_points排名在/ mobile_user节点下,并为他们分配一个排名。我已经成功完成了此操作,但现在我想将相同的10个用户写入另一个名为排行榜的节点。我该怎么做?

这是我当前的函数,已经将它们从1排到10:

    exports.leaderboardUpdate2 = functions.https.onRequest((req, res) =>{
  const updates = [];
  const leaderboard = {};

  const rankref = admin.firestore().collection('mobile_user');
  const leaderboardRef = admin.firestore().collection('leaderboard');

  return rankref.orderBy("earned_points").limit(10).get().then(function(top10) {
      let i = 0;
      console.log(top10)
      top10.forEach(function(childSnapshot) {
        const r = top10.size - i;
        console.log(childSnapshot)
        updates.push(childSnapshot.ref.update({rank: r}));
        leaderboard[childSnapshot.key] = Object.assign(childSnapshot, {rank: r});
        i++;
        console.log(leaderboard)
      });
      updates.push(leaderboardRef.add(leaderboard));
      return Promise.all(updates);
    }).then(() => {
      res.status(200).send("Mobile user ranks updated");
    }).catch((err) => {
      console.error(err);
      res.status(500).send("Error updating ranks.");
    });
});

这成功更新了我所有用户所在的/ mobile_user节点,但是我希望在函数执行后将这10个用户“导出”到排行榜节点。

(请注意,页首横幅节点始终始终只有10条记录)

1 个答案:

答案 0 :(得分:1)

您的Cloud Function中存在两个问题:

首先,您不能直接使用childSnapshot对象(既不能使用Object.assign也不能直接使用)来创建新文档。您必须使用childSnapshot.data(),请参见https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentSnapshot

第二,您使用childSnapshot.key,而应使用childSnapshot.id,请参阅与上述相同的文档。

最后,请注意,使用您的代码结构,users文档将作为地图添加到唯一的leaderboard文档下。我不确定这正是您想要的,因此您可以针对此特定点修改代码。

因此,以下方法应该起作用:

exports.leaderboardUpdate2 = functions.https.onRequest((req, res) => {
  const updates = [];
  const leaderboard = {};

  const rankref = admin.firestore().collection('mobile_user');
  const leaderboardRef = admin.firestore().collection('leaderboard');

  return rankref
    .orderBy('earned_points')
    .limit(10)
    .get()
    .then(function(top10) {
      let i = 0;
      console.log(top10);
      top10.forEach(function(childSnapshot) {
        const r = top10.size - i;
        updates.push(childSnapshot.ref.update({ rank: r }));
        leaderboard[childSnapshot.id] = Object.assign(childSnapshot.data(), {
          rank: r
        });
        i++;
      });
      updates.push(leaderboardRef.add(leaderboard));
      return Promise.all(updates);
    })
    .then(() => {
      res.status(200).send('Mobile user ranks updated');
    })
    .catch(err => {
      console.error(err);
      res.status(500).send('Error updating ranks.');
    });
});

在您发表评论之后,这是一个新版本,该版本在leaderboard集合中为每个mobile_user写了一个文档。请注意,我们使用DocumentReference并将其与set()方法一起使用,如下所示:leaderboardRef.doc(childSnapshot.id).set()

exports.leaderboardUpdate2 = functions.https.onRequest((req, res) => {
  const updates = [];
  const leaderboard = {};

  const rankref = admin.firestore().collection('mobile_user');
  const leaderboardRef = admin.firestore().collection('leaderboard');

  return rankref
    .orderBy('earned_points')
    .limit(10)
    .get()
    .then(function(top10) {
      let i = 0;
      console.log(top10);
      top10.forEach(function(childSnapshot) {
        const r = top10.size - i;
        updates.push(childSnapshot.ref.update({ rank: r }));

        updates.push(
          leaderboardRef.doc(childSnapshot.id).set(
            Object.assign(childSnapshot.data(), {
              rank: r
            })
          )
        );

        i++;
      });

      return Promise.all(updates);
    })
    .then(() => {
      res.status(200).send('Mobile user ranks updated');
    })
    .catch(err => {
      console.error(err);
      res.status(500).send('Error updating ranks.');
    });
});