猫鼬预验证钩子没有射击

时间:2014-12-18 20:27:44

标签: mongoose

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

这个答案告诉我为什么我的init挂钩不会触发HEREprepost init仅在从db加载预先存在的模型时触发。所以我读到validate将在创建新模型时运行。知道我已从pre init切换到pre 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();
})

我知道我无法使用this,因为该文档尚未填充数据。所以这就是为什么我有data,但这似乎仍然不起作用,哦,我得到了我应该从这个answer传入的参数。

任何帮助都将不胜感激。

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

我收到以下错误

service err: CastError: Cast to ObjectId failed for value "[object Object]" at path "location"

这是有道理的,因为在我的模型中它需要ObjectId而不是[object, Object]这就是我所传递的。但是,我以为我可以保存location,获取生成的ObjectId,并在发生错误之前将其存储在组模型中。因此,最初使用pre init直到发现不起作用,现在发现pre validate也不起作用。有没有办法做我正在尝试的事情?

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

  1. 创建位置
  2. 获取新的ObjectId
  3. 将新位置ObjectId存储在组中而不是对象本身
  4. 我尝试将其添加到pre挂钩的原因是我可以在一个位置使用此代码,并在新建组模型时自动处理此问题。

3 个答案:

答案 0 :(得分:6)

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

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

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

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

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

向组架构添加静态方法并注册模型:

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

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

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

答案 1 :(得分:1)

预先(验证)触发" .save"并注意数据没有当前文档。" this"变量会有它。另外注意.pre(验证)会在我们做的时候触发" .save"。下面是一个如何做你正在寻找的例子。我做了它并且它完美地工作

   var mongoose = require('mongoose');
    var Schema = mongoose.Schema;
    //group schema
    var GroupSchema = new Schema({
        location: String,
        pass: String
    });
    //dependant location schema
    var LocationSchema = new Schema({
        city: String
    });

  //here I compile it into a model -groupschema
    var Groupuser = mongoose.model('usertest', GroupSchema, 'usertest');
    //here I compile it into a model-location schema
    var Location = mongoose.model('locationtest', LocationSchema, 'locationtest');


    //here is the pre validate,note this will trigger when we save groupschema realted documents.

    GroupSchema.pre('validate', function(next, data) { //will be triggered before the save
        console.log("inside pre validate", this); //the this will have amsterdam,and test see below.
        if (this.location) {//will be amsterdam
            var location = new Location();
            location.city = this.location//adding amsterdam to the location.city 
            location.save(function(err, data) {//this data will have the location document that we just saved.
            });
        }
        next();
    });

    //now I create a new user for groupschema
    var newuser = new Groupuser();
    newuser.location = 'amsterdam';
    newuser.pass = 'test'
    newuser.save(function(err) { //Before this save function does the save,it triggers the .pre(validatE)
        if (err) return console.log(err);//
    });

我可能没有按照您的意愿确定内部位置功能,但我确定.pre(validate)仅在您执行.save时触发。 它可以是新文档或现有doucment。还要注意,加载模型时不会触发。

1)we define a schema (var schema=new Schma({datatypes})
2)we compile it into a model(var model=mongoose.model('collectionname',schema)
3)we instantiate a new variable of the model(var user=new model(); and then define the values
4) finally we save the data(user.save()->its here that the pre.validate triggers
Hope its clear now

答案 2 :(得分:0)

您的问题很可能是在实际保存位置后调用 ALTER FUNCTION [dbo].[ithc_DateAdd] ( @datePart VARCHAR(5) , @changValue INT , @baseDate DATETIME ) RETURNS DATETIME AS BEGIN DECLARE @returnDate DATETIME SELECT @returnDate = CASE WHEN ( @baseDate = DATEADD(MM, DATEDIFF(MM, -1, @baseDate), 0) - 1 AND( @datePart = 'YY' OR @datePart = 'YEAR') ) THEN DATEADD(MM, DATEDIFF(mm, -1, DATEADD(yy, @changValue, @baseDate)), 0) - 1 WHEN @datePart = 'DD' OR @datePart = 'DAY' THEN DATEADD(DD, @changValue, @baseDate) WHEN @datePart = 'MM' OR @datePart = 'MONTH' THEN DATEADD(MM, @changValue, @baseDate) WHEN @datePart = 'YY' OR @datePart = 'YEAR' THEN DATEADD(YY, @changValue, @baseDate) END RETURN @returnDate END ,因为它被调用异步

如果您要将next()添加到next()内,我相信您应该解决您的问题。

save()