MongoDB查找一半时间返回文档

时间:2019-06-29 21:00:20

标签: database mongodb concurrency mongodb-query

我正在将MongoDB与Express结合使用,并且可以获取用户列表,并根据获得的胜利数对他们进行排序。问题在于,同一代码80%的时间返回没有问题的排序列表,但是20%的响应是空数组[]。

我到处都有承诺,并且我已经交叉检查了问题出在mongoDB的find方法中,而不是sort方法中。我了解并发性和东西,我只是不明白为什么这不起作用。

app.get("/api/account/getSortedRank", (req, res) => {

    const { query } = req;
    const { userId } = query;

    var getFriends = [];

    User.findOne(
      {
        _id: userId
      },
      (err, user) => {
        if (err) {
          console.log("Server error");
        }
        user.friends.forEach(userFound => {
          getFriends.push(userFound.user);
        });

        // getFriends is always correct!

      }
    ).then(() => {
      User.find({
        _id: { $in: getFriends }
      })
        .sort({ wins: -1 })
        .then(sortedUsers => {

          // 50% of the time sortedUsers is an empty array!
          let usersList = [];
          sortedUsers.forEach(user => {
            usersList.push({
              firstName: user.firstName,
              lastName: user.lastName,
              userID: user._id,
              wins: user.wins
            });
          });
          return res.send({
            success: true,
            usersList
          });
        });
    });
  });


1 个答案:

答案 0 :(得分:0)

您在这里混合使用了回调和Promise,这很可能最终会以不同的完成时间执行两次findOne查询。因此,getFriends有时会及时填充,而其他时候则不会。

相反,将find查询移到findOne回调中:

User.findOne(
  {
    _id: userId
  },
  (err, user) => {
    if (err) {
      console.log("Server error");
    }
    var getFriends = [];
    user.friends.forEach(userFound => {
      getFriends.push(userFound.user);
    });

    // getFriends is always correct!
    User.find({
      _id: { $in: getFriends }
    })
      .sort({ wins: -1 })
      .then(sortedUsers => {

        let usersList = [];
        sortedUsers.forEach(user => {
          usersList.push({
            firstName: user.firstName,
            lastName: user.lastName,
            userID: user._id,
            wins: user.wins
          });
        });
        return res.send({
          success: true,
          usersList
        });
      });
  }
);