我正在尝试创建一个模型,然后使用mongoose创建另一个模型并保存对原始模型的引用。我一直在浏览mongoose关于中间件及其钩子的文档,但其中一些似乎没有触发。
这个答案告诉我为什么我的init挂钩不会触发HERE,pre
和post
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
也不起作用。有没有办法做我正在尝试的事情?
以下是我按顺序尝试的内容:
ObjectId
ObjectId
存储在组中而不是对象本身我尝试将其添加到pre
挂钩的原因是我可以在一个位置使用此代码,并在新建组模型时自动处理此问题。
答案 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()