我有一个用户模型,使用一些属性创建,以后在用户激活后删除 . 我注意到在用户启动forgotPassword请求后,这些属性重新出现 .

当我单步执行代码(它是一个快速应用程序)时,我在forgetPassword控制器中有一个User.findOne请求,它返回一个仍然具有已删除属性的用户文档,因此当我保存时,它们会被保存回数据库密码重置令牌 .

function forgotPassword(req, res, next) {
  const username = req.body.username;

  // Generate token
  const token = uuid.v4();

  // Find the user
  User.findOne({ username: username }, function(err, user) {
    if (err) {
      return next(err);
    }
    // At this stage user also has the properties that 
    // were previously deleted when I inspect it
    user.resetToken = token;
    user.save(function(err, savedUser, numAffected) { 
      // So resetToken gets saved but also the previously deleted properties
      ...
    });

我在数据库中验证了它们在用户激活时被删除,然后在forgotPassword请求后重新出现 .

是否存在Mongoose对findOne请求所做的某种缓存?

我查看了Mongoose github问题并没有找到任何结果 . Mongoose findOne在封面下使用mquery但我看不到缓存层 .

如何让Mongoose使用数据库中的实时数据?

更新了最小的例子:

[更新:我没有在最小的例子中添加任何快速路由,但事件的顺序基本相同,但在真实的应用程序中,db调用分散在几个不同的快速路由上]

的package.json:

{
  "name": "minimal-mongoose-findone-old-data-issue",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chance": "^1.0.11",
    "mongoose": "^4.12.4",
    "uuid": "^3.1.0"
  }
}

index.js:

const mongoose = require('mongoose');  
const uuid = require('uuid');
const chance = new(require('chance'));

const dbPort = process.env.DBPORT;
const dbName = 'minimal-mongoose-findone-old-data-issue';

const mongoUrl = `mongodb://localhost:${dbPort}/${dbName}`;
mongoose.connect(mongoUrl, { user: '', pass: '' });
mongoose.set("debug",true);

const UserSchema = new mongoose.Schema({
  username: {
    type: String,
    unique: true
  },
  activationToken: {
    type: String,
    default: uuid.v4()
  },
  active: {
    type: Boolean,
    default: false
  },
  passwordToken: {
    type: String
  }
}, { timestamps: true });

const User = mongoose.model('User', UserSchema);

// Create user
const username = chance.first();
const user = new User();
user.username = username;
user.save(function(err, savedUser) {
  if (err) { throw err };
  console.log(`STEP 1: user created: ${JSON.stringify(savedUser, 0, 2)}`);

  // Activate user
  User.findOne({
    activationToken: savedUser.activationToken
  }, function(err, foundUser) {
    if (err) { throw err };
    console.log(`STEP 2: user found: ${JSON.stringify(foundUser, 0, 2)}`);
    foundUser.active = true;
    foundUser.activationToken = undefined;
    foundUser.save(function(err, activatedUser, numAffected) {
      if (err) { throw err };
      console.log(`STEP 3: user activated: ${JSON.stringify(activatedUser, 0, 2)}`);

      // Reset password
      User.findOne({
        username: username,
      }, function(err, resetPasswordUser) {
        if (err) { throw err };
        console.log(`STEP 4: user found for password reset: ${JSON.stringify(resetPasswordUser, 0, 2)}`);
        // Password reset logic here etc...
        // The problem is that since the second findOne call returns old data, 
        // the activationToken gets saved back to the database when I save resetPasswordUser
        process.exit();
      });
    });
  });
});

在STEP 3中,console.log输出没有activationToken

在STEP 4中,activationToken返回console.log输出

运行节点index.js的输出:[使用mongo调试输出更新]

Mongoose: users.insert({ updatedAt: new Date("Wed, 25 Oct 2017 08:02:48 GMT"), createdAt: new Date("Wed, 25 Oct 2017 08:02:48 GMT"), username: 'Hannah', _id: ObjectId("59f045287a2de871d0fbce14"), active: false, activationToken: 'c9048f36-02c7-4a0f-8e2c-abf5cb9120fe', __v: 0 })
STEP 1: user created: {
  "__v": 0,
  "updatedAt": "2017-10-25T08:02:48.107Z",
  "createdAt": "2017-10-25T08:02:48.107Z",
  "username": "Hannah",
  "_id": "59f045287a2de871d0fbce14",
  "active": false,
  "activationToken": "c9048f36-02c7-4a0f-8e2c-abf5cb9120fe"
}
Mongoose: users.findOne({ activationToken: 'c9048f36-02c7-4a0f-8e2c-abf5cb9120fe' }, { fields: {} })
STEP 2: user found: {
  "_id": "59f045287a2de871d0fbce14",
  "updatedAt": "2017-10-25T08:02:48.107Z",
  "createdAt": "2017-10-25T08:02:48.107Z",
  "username": "Hannah",
  "__v": 0,
  "active": false,
  "activationToken": "c9048f36-02c7-4a0f-8e2c-abf5cb9120fe"
}
Mongoose: users.update({ _id: ObjectId("59f045287a2de871d0fbce14") }, { '$unset': { activationToken: 1 }, '$set': { active: true, updatedAt: new Date("Wed, 25 Oct 2017 08:02:48 GMT") } })
STEP 3: user activated: {
  "_id": "59f045287a2de871d0fbce14",
  "updatedAt": "2017-10-25T08:02:48.153Z",
  "createdAt": "2017-10-25T08:02:48.107Z",
  "username": "Hannah",
  "__v": 0,
  "active": true
}
Mongoose: users.findOne({ username: 'Hannah' }, { fields: {} })
STEP 4: user found for password reset: {
  "_id": "59f045287a2de871d0fbce14",
  "updatedAt": "2017-10-25T08:02:48.153Z",
  "createdAt": "2017-10-25T08:02:48.107Z",
  "username": "Hannah",
  "__v": 0,
  "active": true,
  "activationToken": "c9048f36-02c7-4a0f-8e2c-abf5cb9120fe"
}

在运行index.js后的mongo shell中:

MongoDB shell version: 3.2.4
connecting to: test
> use minimal-mongoose-findone-old-data-issue
switched to db minimal-mongoose-findone-old-data-issue
> db.users.find({ username: 'Hannah'}).pretty()
{
    "_id" : ObjectId("59f045287a2de871d0fbce14"),
    "updatedAt" : ISODate("2017-10-25T08:02:48.153Z"),
    "createdAt" : ISODate("2017-10-25T08:02:48.107Z"),
    "username" : "Hannah",
    "active" : true,
    "__v" : 0
}