架构错误,'没有方法保存'

时间:2015-01-23 01:04:57

标签: javascript node.js mongodb mongoose mongodb-query

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

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,因为我无法保存。我应该怎么做才能将它保存到数据库中?

2 个答案:

答案 0 :(得分:1)

您的代码中的问题是.find()不会返回单个mongoose文档,而是返回一个文档数组,即使该数组只包含一个项目。您可以通过调用.findOne()甚至.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":和类似字段。这些对于查询很有用,返回"长度"并不是一件简单的事情。没有阅读整个文档的数组:

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运算符增加计数器值。要执行相反操作并删除关注者,请使用$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()

因为你使用的是猫鼬,不要忘记你还在使用MongoDB。最好使用数据库运算符来修改文档,而不是在代码中进行修改。

阅读文档中的queryupdate运算符。事实上,请阅读all of them,因为值得学习。

答案 1 :(得分:0)

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

.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!"})
  });
})