Mongoose - 使用嵌套模型升级文档

时间:2012-09-30 18:50:49

标签: javascript node.js mongodb express mongoose

我的快递应用程序中有一个带有'checked_in'标志的基本文档:

module.exports = Book= mongoose.model('Book', new Schema({
 name : String,
 checked_in : Boolean
},{ collection : 'Book' }));

我想记录书籍的签入和退出时间,以便我想出另一种架构:

var action = new Schema({
 checked_in: Boolean,     
});

module.exports = Activity = mongoose.model('Activity', new Schema({
 book_id: String,
 actions: [action]
},{ collection : 'Activity' }));

'book_id'应该是图书的文档ID,当我更新图书时,我需要创建或更新该图书的活动日志,并在操作中添加新项目:

exports.update = function(req, res){  
    return Book.findById(req.params.id, function(err, book) {  
       var activity = new Activity({book_id: book.id});
       activity.actions.push({
           checked_in: req.body.checked_in,
       });

       Activity.update({ book_id: book.id}, activity.toObject(), { upsert: true }));

       book.checked_in = req.body.checked_in;
       return device.save(function(err) {
           return res.send(book);
       });
    });
};

我遇到的问题是没有任何内容插入到Activity集合中。如果我使用.save(),那么我只是在集合中获得了大量重复。

更新

我已经开始使用下面给出的建议重新处理事情,但我仍然没有运气。这就是我现在所拥有的:

module.exports = Activity = mongoose.model('Activity', new Schema({
  book_id: Schema.ObjectId,
  actions: [new Schema({
    checked_in: Boolean,
    last_user: String
  })]
},{ collection : 'Activity' }));

现在是更新代码:

exports.update = function(req, res){  
  // TODO: Check for undefined.
  return book.findById(req.params.id, function(err, book) {    
    if(!err) {
      // Update the book.
      book.checked_in = req.body.checked_in;
      book.last_user = req.body.last_user;    
      book.save();

      // If there's no associated activity for the book, create one. 
      // Otherwise update and push new activity to the actions array.
      Activity.findById(book._id, function (err, activity) {
        activity.actions.push({
          checked_in: req.body.checked_in,
          last_user: req.body.last_user
        })

        activity.save();      
      });
    }
  });
};

我想要最终得到的是每本书的文档,其中包含一系列检查/插件,每当有人检查或退出书籍时都会更新。即:

{
    book_id: "5058c5ddeeb0a3aa253cf9d4",
    actions: [
        { checked_in: true, last_user: 'ralph' },
        { checked_in: true, last_user: 'gonzo' },
        { checked_in: true, last_user: 'animal' }
    ]
}

最终我会在每个条目中加上时间戳。

2 个答案:

答案 0 :(得分:2)

我看到一些可以改进的事情......

  • book_id模型中的Activity字段应为Schema.ObjectId而非String。如果愿意,您可以使用populate。

  • 您没有在exports.update中进行任何错误检查。如果用户传入了无效的id,您需要检查book是否未定义,以及常见的if (err) return next(err)(这需要您的函数参数{{1} }})。

  • res, res, next中创建活动时,您希望使用exports.update代替book._id

  • 不需要所有book.id语句

  • return变量未在任何地方声明,我不确定您要保存的内容......我认为您的意思是device

然后,您只需book该活动,而不是.save()

答案 1 :(得分:2)

有几个问题:

  1. 您正在尝试使用findById使用图书的ID代替活动的ID来查找图书的活动文档。
  2. 您没有处理图书的活动文档尚不存在的情况。
  3. 请改为尝试:

    Activity.findOne({book_id: book._id}, function (err, activity) {
      if (!activity) {
        // No Activity doc for the book yet, create one.
        activity = new Activity({book_id: book._id});
      }
      activity.actions.push({
        checked_in: req.body.checked_in,
        last_user: req.body.last_user
      });
    
      activity.save();
    });