首页 > 解决方案 > MongoDB find 一半时间返回文档

问题描述

我正在将 MongoDB 与 Express 一起使用,并且我有一个 fetch 来获取用户列表并按照他们获得的胜利数量对他们进行排序。问题是 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
          });
        });
    });
  });


标签: databasemongodbconcurrencymongodb-query

解决方案


您在这里混合了回调和承诺,这可能最终会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
        });
      });
  }
);

推荐阅读