4

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

这个作品找到了。在我的用户界面中,我可以将新用户添加到旅行中,代码如下:

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

问题是,当我更新我的架构时,旅行中的现有用户被填充,这意味着存储为旅行中没有 ID 的对象,新用户在旅行中存储为 ObjectId。在我更新之前,如何确保填充的用户返回到 ObjectId?否则更新将失败并出现 CastError。

看这里的错误

4

2 回答 2

2

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

首先,我尝试将添加到列表与保存分开。因此,在您的示例中,请trip._users.push(user._id);移出 $save 功能。我将这样的操作放在事物的客户端,因为我希望 UI 在持久化它们之前显示更改。

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

因此,现在您应该使用一致的填充用户列表。在服务器代码中,就在调用 $update 之前,我将 trip._users 替换为 ObjectId 列表。换句话说,“取消填充”_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。

于 2013-10-25T15:57:23.227 回答
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);
  })
};

这对我来说很好,我希望也能和你一起工作

于 2017-07-25T16:44:29.730 回答