tl; dr
是的,null
在强制执行唯一的“实际”值的同时,可能会有多个文档的字段设置为或未定义。
要求:
- MongoDB v3.2 +。
- 事先了解您的具体价值类型(例如,始终为a
string
或object
不为时null
)。
如果您对这些细节不感兴趣,请随时跳到本implementation
部分。
更长的版本
为了补充@Nolan的答案,从MongoDB v3.2开始,您可以使用带有过滤表达式的部分唯一索引。
部分过滤器表达式具有局限性。它只能包括以下内容:
- 等式表达式(即字段:值或使用
$eq
运算符),
$exists: true
表达,
$gt
,$gte
,$lt
,$lte
表情,
$type
表达式,
$and
仅限顶级运营商
这意味着{"yourField"{$ne: null}}
无法使用平凡的表达式。
但是,假设您的字段始终使用相同的类型,则可以使用$type
expression。
{ field: { $type: <BSON type number> | <String alias> } }
MongoDB v3.6添加了对指定多种可能类型的支持,这些类型可以作为数组传递:
{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }
这意味着它允许在不允许的情况下使用多种类型中的任何一种null
。
因此,如果我们要允许email
以下示例中的字段接受一个值string
或binary data
一个值,则合适的$type
表达式为:
{email: {$type: ["string", "binData"]}}
实施
猫鼬
您可以在猫鼬模式中指定它:
const UsersSchema = new Schema({
name: {type: String, trim: true, index: true, required: true},
email: {
type: String, trim: true, index: {
unique: true,
partialFilterExpression: {email: {$type: "string"}}
}
}
});
或直接将其添加到集合中(使用本地的node.js驱动程序):
User.collection.createIndex("email", {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
});
本机mongodb驱动程序
使用 collection.createIndex
db.collection('users').createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
},
function (err, results) {
// ...
}
);
mongodb外壳
使用db.collection.createIndex
:
db.users.createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {$type: "string"}
}
})
这将允许插入多个记录并附带null
一封电子邮件,或者根本没有一个电子邮件字段,但不能插入相同的电子邮件字符串。