【问题标题】:MongoDB find returns documents half the timeMongoDB find 一半时间返回文档
【发布时间】:2019-06-29 21:00:20
【问题描述】:

我正在将 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
          });
        });
    });
  });


【问题讨论】:

  • Friends 来自哪里?
  • Friends 是一个包含用户ID 的数组,它总是被正确地构造并且它不应该引起任何问题。当我返回一个空数组时,Friends 不为空。
  • 查询本身看起来不错,所以问题很可能是 Friends 根本不包含任何匹配的 _id 值。
  • 但是为什么它会在一半的时间内起作用呢?这就是我构造朋友的方式: const { query } = req;常量 { userId } = 查询; User.findOne( { _id: userId }, (err, user) => { if (err) { console.log("服务器错误"); } user.friends.forEach(userFound => { getFriends.push(userFound. user); }); return getFriends } ).then((getFriends) => { User.find({ _id: { $in: getFriends } }) ...
  • 完成。我认为问题在于我需要返回一些值并使用 'then( (importedValue) => blahblah... 但是,为什么它会在一半的时间里起作用!?

标签: database mongodb concurrency mongodb-query


【解决方案1】:

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

【讨论】:

  • 非常感谢这个,我虽然只有在 getFriends 填充后才会执行 then(() => {}) ,但是一旦找到用户就会执行,因此 getFriends 并不总是按时构建。
猜你喜欢
  • 2021-11-07
  • 2015-06-09
  • 2015-09-02
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-19
相关资源
最近更新 更多