2012-09-30 300 views
0

我有一个“checked_in”标志的基本文件在我的快递应用Upserting文件:猫鼬与嵌套模型

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); 
     }); 
    }); 
}; 

我遇到的问题是什么都没有插入到活动集合中。如果我使用.save(),那么我只是在集合中获取大量重复项。

UPDATE

我已经开始重新工作的事情与下面给出的意见,但我仍然没有任何这方面的运气。这是我现在有:

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' } 
    ] 
} 

最终我会在每个条目中有一个时间戳。

+0

代码更新后,有什么特别不工作,你需要哪些帮助? – JohnnyHK

+0

它不会创建新的活动,可能是因为我在使用findById。但是,如果我只是使用.save(),我最终会得到大量相同书目ID的重复文档。 – backdesk

+0

“upserting”是什么意思? – chovy

回答

2

有几个问题:

  1. 你试图使用findById使用本书的ID,而不是活动的id的找书的活动文档。
  2. 您不处理书本活动文档尚不存在的情况。

试试这个:

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(); 
}); 
+0

这实际上是有意义的(和工程)。尽管我相信查询应该是{book_id:book.id},而不是我收集的book._id。我头脑中有一个愚蠢的想法,那就是猫鼬会自动地从相应的身份证件中找出事物。我很快就会把所学到的一切都写出来。谢谢:) – backdesk

+0

@Crungmungus'book.id'是一个stringized [别名](http://mongoosejs.com/docs/guide.html#id)给'book._id',这是Mongoose默认添加的。因此,要么是有效的,但'book.id'不是很有效,因为Mongoose必须将它转换回ObjectId以执行'findOne'查询。 – JohnnyHK

2

我看可以改善一些东西......

  • Activity模型book_id场应该是Schema.ObjectId而不是String。如果你愿意,你将可以使用填充。

  • 您在exports.update中没有执行任何错误检查。如果用户通过了一个无效的id,那么您需要检查book是否未定义,以及常见的if (err) return next(err)(这需要您的函数参数为res, res, next)。

  • 当您在exports.update活动中,要使用book._id代替book.id

  • 不需要

  • device变量所有return语句不被任何声明,我不是确定你正在努力拯救什么......我想你的意思是book那里。

然后,您可以只.save()活动,而不是做Activity.update