我已经在我的模型中定义了一个独特的字段,但是当我尝试测试它时似乎没有被风帆检查,因为我得到Error (E_UNKNOWN) :: Encountered an unexpected error:
MongoError: E11000 duplicate key error index:
而不是风帆ValidationError。
在帆中处理独特区域的最佳方法是什么?
// model/User.js
module.exports{
attributes: {
email: {required: true, unique: true, type: 'email' },
....
}
// in my controller
User.create({email: 'hello@gmail.com'}).then(...).fail(....)
User.create({email: 'hello@gmail.com'}).then(...).fail(// throws the mongo error )
// and same goes with update it throws error
先谢谢你们。
答案 0 :(得分:9)
目前unique
属性only creates a unique index in MongoDB。
您可以使用beforeValidate()
回调来检查具有该属性的现有记录,并将结果保存在类变量中。
此方法可确保您的模型返回适当的验证错误,客户可以对此进行评估。
var uniqueEmail = false;
module.exports = {
/**
* Custom validation types
*/
types: {
uniqueEmail: function(value) {
return uniqueEmail;
}
},
/**
* Model attributes
*/
attributes: {
email: {
type: 'email',
required: true,
unique: true, // Creates a unique index in MongoDB
uniqueEmail: true // Makes sure there is no existing record with this email in MongoDB
}
},
/**
* Lifecycle Callbacks
*/
beforeValidate: function(values, cb) {
User.findOne({email: values.email}).exec(function (err, record) {
uniqueEmail = !err && !record;
cb();
});
}
}
修改强>
正如thinktt所指出的那样,我以前的解决方案中存在一个错误,它使默认的uniqueEmail
值无用,因为它在模型声明本身中定义,因此无法在模型代码中引用。我已经相应地编辑了我的答案,谢谢。
答案 1 :(得分:5)
在将电子邮件定义为唯一字段后,您正尝试使用相同的电子邮件地址创建两个用户。
也许您可以通过该电子邮件地址查询用户 - 如果已经存在 - 返回错误或更新该用户。
var params = {email: 'email@email.com'};
User.findOne(params).done(function(error, user) {
// DB error
if (error) {
return res.send(error, 500);
}
// Users exists
if (user && user.length) {
// Return validation error here
return res.send({error: 'User with that email already exists'}, 403.9);
}
// User doesnt exist with that email
User.create(params).done(function(error, user) {
// DB error
if (error) {
return res.send(error, 500);
}
// New user creation was successful
return res.json(user);
});
});
Sails.js & MongoDB: duplicate key error index
在Sails.js文档中还有一些关于唯一模型属性的有趣内容 https://github.com/balderdashy/waterline#indexing
编辑: 从http://sailsjs.org/#!documentation/models
拉出来可用的验证有:
空,必需,notEmpty,undefined,字符串,alpha,数字,字母数字,电子邮件,url,urlish,ip,ipv4,ipv6,creditcard,uuid,uuidv3,uuidv4,int,integer,number,finite,decimal,float ,falsey,truthy,null,notNull,boolean,array,date,hexadecimal,hexColor,lowercase,uppercase,after,before,is,regex,not,notRegex,equals,contains,notContains,len,in,notIn,max,min ,minLength,maxLength
答案 2 :(得分:2)
@tvollstaedt和David的解决方案发布了工作,但这段代码存在很大问题。我整天都在苦苦挣扎,所以我提出了这个稍微修改过的答案。我只是评论,但我还没有得分。我很乐意删除这个答案,如果他们可以更新他们的,但我真的想帮助那些遇到同样问题的人。
使用自定义验证程序的上述代码的问题是您无法访问属性" uniqueEmail"从以前的解决方案试图做的女巫的方式。它在这些解决方案中工作的唯一原因是因为它们无意中抛出了“独特的电子邮件”。进入全球空间。
以下是不使用全局空间的tvollstaedt代码的略微修改。它定义了modual.exports之外的uniqueEmail,因此它只限于模块,但可以在整个模块中访问。
可能还有更好的解决方案,但这是我能想到的最好的解决方案。
var uniqueEmail = false;
module.exports = {
/**
* Custom validation types
*/
types: {
uniqueEmail: function(value) {
return uniqueEmail;
}
},
/**
* Model attributes
*/
attributes: {
email: {
type: 'email',
required: true,
unique: true, // Creates a unique index in MongoDB
uniqueEmail: true // Makes sure there is no existing record with this email in MongoDB
}
},
/**
* Lifecycle Callbacks
*/
beforeValidate: function(values, cb) {
User.findOne({email: values.email}).exec(function (err, record) {
uniqueEmail = !err && !record;
cb();
});
}
};
答案 3 :(得分:0)
@tvollstaedt你的反应就像一个魅力,顺便说一下,处理"唯一性"到目前为止在sailsjs。
谢谢!
以下是使用" sails-validation-messages"添加自定义验证消息的两分钱:
st = {sub[0] for sub in y}
x[:] = (sub for sub in x if sub[0] not in st)

然后在控制器中你可以像这样处理错误:
module.exports = {
/* Custom validation types */
uniqueEmail: false,
types: {
uniqueEmail: function(value) {
return uniqueEmail;
}
},
attributes: {
firstname:{
type: 'string',
required: true,
},
lastname:{
type: 'string',
required: true,
},
email:{
type: 'email',
required: true,
unique: true,
maxLength:50,
uniqueEmail:true
},
status:{
type: 'string'
}
},
beforeValidate: function(values, cb) {
Application.findOne({email: values.email}).exec(function (err, record) {
console.log('before validation ' + !err && !record);
uniqueEmail = !err && !record;
cb();
});
},
validationMessages: {
firstname: {
required : 'First name is required',
},
lastname: {
required : 'Last name is required',
},
email: {
required : 'Email is required',
email : 'Enter valid email',
uniqueEmail: 'Email already registered'
},
}
};

由于
答案 4 :(得分:0)
正确的方法!!!
module.exports = {
schema: true,
migrate: 'safe',
tableName: 'users',
autoCreatedAt: false,
autoUpdatedAt: false,
adapter: 'mysql',
/**
* Custom validation types
*/
types: {
uniquePhone: function(value) {
return value!=='_unique';
}
},
attributes: {
id: {
type: 'integer',
primaryKey: true,
unique: true,
autoIncrement: true
},
email: {
type: 'email'
},
first_name: {
type: 'string'
},
last_name: {
type: 'string'
},
phone: {
type: 'string',
required: true,
uniquePhone: true
}
},
/**
* Lifecycle Callbacks
*/
beforeValidate: function(values, cb) {
Users.findOne({phone: values.phone}).exec(function(err, record) {
// do whatever you want check against various scenarios
// and so on..
if(record){
values.phone='_unique';
}
cb();
});
}
};
通过这种方式,我们不会破坏验证器的概念!
答案 5 :(得分:0)
在最新版本的Sails v1.2.7中,回调不再起作用。如果您遇到无法在模型上使用唯一性的问题(例如我对sails-mongo所做的操作),则需要在控制器中手动配置它。
这是一个例子
//SIGNUP
create: async (req, res) => {
const { name, email, password } = req.body;
try {
const userExists = await sails.models.user.findOne({ email });
if (userExists) {
throw 'That email address is already in use.';
}
}