猫鼬预验证钩子没有射击

gma*_*iac 6 mongoose

我正在尝试创建一个模型然后创建另一个模型并使用mongoose保存对原始模型的引用.我一直在浏览mongoose关于中间件及其钩子的文档,但其中一些似乎没有触发.

这个答案告诉我为什么我的init钩子不会在这里触发,pre并且post init只在从db加载预先存在的模型时触发.所以我读到validate会在创建新模型时运行.知道我从切换pre initpre validate.

这是我想要做的代码:

GroupSchema.pre('validate', function (next, data) {
    console.log("inside pre validate");
    if (data.location) {
        location = new Location(data.location);
        data.location = location._id;
        location.save(function (err) {
            if (err) handleError(err);
        });
    }

    next();
})
Run Code Online (Sandbox Code Playgroud)

我知道我无法使用,this因为该文档尚未填充数据.这就是为什么我有data,但这似乎仍然没有用,哦,我得到了我应该从这个答案传递的参数.

任何帮助,将不胜感激.

**************UPDATE**************

为了增加一些清晰度,使用答案中建议的内容并将我的pre validate功能更改为:

GroupSchema.pre('validate', function (next, data) {
    console.log("inside pre validate", this);
    if (this.location) {
        location = new Location(this.location);
        this.location = location._id;
        location.save(function (err) {
            if (err) handleError(err);
        });
    }

    next();
})
Run Code Online (Sandbox Code Playgroud)

我收到以下错误

service err: CastError: Cast to ObjectId failed for value "[object Object]" at path "location"
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为在我的模型中它期望一个ObjectId而不是[object, Object]我传递的东西.但是,我以为我可以保存location,获取ObjectId生成的内容并将其存储在组模型中,然后再抛出错误.因此,最初使用pre init直到发现不起作用,现在发现这pre validate也行不通.有什么方法可以做我正在尝试的事情吗?

以下是我按顺序尝试的内容:

  1. 创造位置
  2. 得到新的 ObjectId
  3. 将新位置存储ObjectId在组中而不是Object本身

我试图将它添加到pre钩子的原因是我可以将这个代码放在一个位置,它会在新建一个组模型时自动处理这个问题.

Joh*_*yHK 6

你想要做的事情并不适合 validate或任何其他中间件,因为您需要提供位置数据以及创建组本身所需的内容.

更合适的是创建一个静态方法 GroupSchema,显式执行此增强的创建函数.

因此,假设基本位置和组模式如下:

var LocationSchema = new Schema({
    city: String,
    state: String
});

var GroupSchema = new Schema({
    name: String,
    location: {type: ObjectId, ref: 'Location'}
});
Run Code Online (Sandbox Code Playgroud)

将静态方法添加到组模式并注册模型:

GroupSchema.statics.createWithLocation = function(group, location, callback) {
    Location.create(location, function(err, location) {
        if (err) return callback(err);
        group.location = location._id;
        Group.create(group, callback);
    });
};

var Location = mongoose.model('Location', LocationSchema);
var Group = mongoose.model('Group', GroupSchema);
Run Code Online (Sandbox Code Playgroud)

通过单独传递组和位置数据参数来调用新方法:

Group.createWithLocation(
    {name: 'group1'}, 
    {city: 'New York', state: 'NY'},
    function(err, group) {
        console.log('group created with location: ', group);
    }
);
Run Code Online (Sandbox Code Playgroud)