Mongoose - 填充后更新(Cast Exception)

时间:2013-10-16 19:24:01

标签: mongodb mongoose

我无法更新我的mongoose架构,因为CastERror会产生意义,但我不知道如何解决它。

旅行模式:

var TripSchema = new Schema({
    name: String,
    _users: [{type: Schema.Types.ObjectId, ref: 'User'}]
});

用户架构:

var UserSchema = new Schema({
    name: String,
    email: String,
});

在我的html页面中,我可以为此行程添加新用户,我通过调用Schema上的findById方法检索数据:

exports.readById = function (request, result) {
    Trip.findById(request.params.tripId).populate('_users').exec(function (error, trip) {
        if (error) {
            console.log('error getting trips');
        } else {
            console.log('found single trip: ' + trip);
            result.json(trip);
        }
    })
};

这个作品找到了。在我的ui中,我可以为旅行添加新用户,这里是代码:

var user = new UserService();
user.email = $scope.newMail;
user.$save(function(response){   
    trip._users.push(user._id);
    trip.$update(function (response) {
        console.log('OK - user ' + user.email + ' was linked to trip ' + trip.name);

        // call for the updated document in database
        this.readOne();
    })
};

问题在于,当我更新我的Schema时,将填充旅行中的现有用户,意味着存储为旅行中不是id的对象,新用户在旅行中存储为ObjectId。 在更新之前,如何确保填充的用户返回到ObjectId?否则更新将因CastError而失败。

see here for error

2 个答案:

答案 0 :(得分:2)

我一直在寻找一种优雅的方式来处理这个问题而没有找到一个令人满意的解决方案,或者至少有一个我对使用填充时mongoosejs人们的想法充满自信。尽管如此,这是我采取的路线:

首先,我尝试将保存添加到列表中。因此,在您的示例中,将trip._users.push(user._id);移出$ save函数。我把这样的动作放在客户端,因为我希望UI在我坚持之前显示更改。

其次,在添加用户时,我一直在使用填充的模型 - 也就是说,我没有push(user._id),而是添加完整的用户:push(user)。这使_users列表保持一致,因为其他用户的id在填充期间已经被相应的对象替换。

所以现在你应该使用一致的填充用户列表。在服务器代码中,在调用$ update之前,我将trip._users替换为ObjectIds列表。换句话说,“un-populate”_users:

user_ids = []
for (var i in trip._users){
    /* it might be a good idea to do more validation here if you like, to make
     * sure you don't have any naked userIds in this array already, as you would
     */in your original code.
    user_ids.push(trip._users[i]._id);
}
trip._users = user_ids;
trip.$update(....

当我再次阅读您的示例代码时,看起来您要添加到旅程中的用户可能是新用户?我不确定这是否仅仅是出于问题目的的简化遗留问题,但如果没有,则需要先保存用户,以便mongo可以在保存行程之前分配ObjectId。

答案 1 :(得分:0)

我编写了一个接受数组的函数,并在回调中返回一个ObjectId数组。要在NodeJS中异步执行,我使用的是async.js。功能如下:

let converter = function(array, callback) {
  let idArray;
  async.each(array, function(item, itemCallback) {
    idArray.push(item._id);
    itemCallback();
  }, function(err) {
    callback(idArray);
  })
};

这对我来说完全没问题,我希望也能和你一起工作