架构错误,'has no method save'

Schema Error, 'has no method save'

目前我想做的是,一旦用户登录,他就可以转到任何用户的 url 并关注他们。我遇到了这个问题

TypeError: Object { _id: 54bd6b90b7d4cc8c10b40cbd,
  name: 'Johnny',
  username: 'batman',
  __v: 0,
  following: [],
  followers: [] } has no method 'save'

schema.js

var UserSchema = new Schema({
    name: String,
    username: { type: String, required: true, index: { unique: true }},
    password: { type: String, required: true, select: false },
    level: String,
    followers: [{ type: Schema.Types.ObjectId, ref: 'User'}],
    following: [{ type: Schema.Types.ObjectId, ref: 'User'}]
});

module.exports = mongoose.model('User', UserSchema);

api.js

        // this is where I'm Stuck ( Should I use put or post? for best practices)

        .post(function(req, res) {

            // find a current user that has logged in
            User.find({ _id: req.decoded.id }, function(err, user) {

                // simply follow the user by matching the id
                user.following = req.params.user_id;

                // save to the database ( The problem )
                user.save(function(err) {
                    if(err) res.send(err);

                    res.json({ message: "Successfully followed!"})
                })
            });
        })

问题出在 .post 中,因为我无法保存。我应该怎么做才能将其保存到数据库中?

您应该使用更新方法,因为这将执行原子操作并且不容易出现任何并发问题。这是因为它会同时执行查找查询和保存。

.post(function(req, res) {

  User.update({ _id: req.decoded.id }, { $push: {following: req.params.user_id }}, function(err, user) {
    if (err) return res.send(err);

    res.json({ message: "Successfully followed!"})
  });
})  

您的代码中的问题是 .find() does not return a single mongoose document but rather an array of documents even if that array contains only a single item. You can correct this by calling .findOne() or even .findById 允许更短的形式。

如前所述,这仍然存在问题,因为无法保证服务器上的文档在您发出 .save() after making modifications. For this reason MongoDB provides an.update()` 方法之前尚未更改,该方法只会进行其他更改通过指定的运算符到文档。

要添加新的关注者,您需要$push将元素添加到数组中:

.post(function(req, res) {

  User.update(
    { 
        "_id": req.decoded.id, 
        "following": { "$ne": req.params.user_id }
    }, 
    { "$push": { "following": req.params.user_id }}, 
    function(err, user) {
      if (err) return res.send(err);

      res.json({ message: "Successfully followed!"})
    }
  );
})  

我实际检查该元素是否 存在,然后仅在出现这种情况时更新。有一个 $addToSet 运算符可以执行此操作,但我还建议修改您的架构以包含 "followingCount": 和类似字段。这些对于查询很有用,在不阅读整个文档的情况下 return 数组的 "length" 并不是一件简单的事情:

var UserSchema = new Schema({
    name: String,
    username: { type: String, required: true, index: { unique: true }},
    password: { type: String, required: true, select: false },
    level: String,
    followers: [{ type: Schema.Types.ObjectId, ref: 'User'}],
    following: [{ type: Schema.Types.ObjectId, ref: 'User'}],
    folloersCount: Number,
    followingCount: Number
});

// And in later code

  User.update(
    { 
        "_id": req.decoded.id, 
        "following": { "$ne": req.params.user_id }
    }, 
    { 
        "$push": { "following": req.params.user_id }},
        "$inc": { "followingCount": 1 }
    },
    function(err, user) {
      if (err) return res.send(err);

      res.json({ message: "Successfully followed!"})
    }
  );
})  

使用 $inc operator. To do the reverse and remove a follower use $pull

增加计数器值
  User.update(
    { 
        "_id": req.decoded.id, 
        "following": req.params.user_id 
    }, 
    { 
        "$pull": { "following": req.params.user_id }},
        "$inc": { "followingCount": -1 }
    },
    function(err, user) {
      if (err) return res.send(err);

      res.json({ message: "Successfully Un-followed :("})
    }
  );
})  

当查询条件不满足时,$addToSet 不能也不会触及文档。

如果您想要在响应中修改文档,请改用 .findOneAndUpdate()

所以不要因为你在使用 mongoose,就忘记了你基本上还在使用 MongoDB。最好使用数据库操作符来修改文档,而不是在代码中进行这些修改。

阅读 query and update operators in the documentation. In fact read up on all of them,因为它值得学习。