tl; dr
Sí, es posible tener varios documentos con un campo configurado nullo no definido, mientras se aplican valores "reales" únicos.
requisitos :
- MongoDB v3.2 +.
- Conocer sus tipos de valores concretos de antemano (por ejemplo, siempre a
stringo objectcuándo no null).
Si no está interesado en los detalles, no dude en pasar a la implementationsección.
versión más larga
Para complementar la respuesta de @ Nolan, comenzando con MongoDB v3.2, puede usar un índice único parcial con una expresión de filtro.
La expresión de filtro parcial tiene limitaciones. Solo puede incluir lo siguiente:
- expresiones de igualdad (es decir, campo: valor o usando el
$eqoperador),
$exists: true expresión,
$gt, $gte, $lt, $lteExpresiones,
$type expresiones,
$and operador en el nivel superior solamente
Esto significa que {"yourField"{$ne: null}}no se puede utilizar la expresión trivial .
Sin embargo, asumiendo que su campo siempre usa el mismo tipo , puede usar una $typeexpresión .
{ field: { $type: <BSON type number> | <String alias> } }
MongoDB v3.6 agregó soporte para especificar múltiples tipos posibles, que se pueden pasar como una matriz:
{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }
lo que significa que permite que el valor sea de varios tipos múltiples cuando no null.
Por lo tanto, si queremos permitir que el emailcampo del ejemplo siguiente acepte valores stringo, digamos binary data, una $typeexpresión adecuada sería:
{email: {$type: ["string", "binData"]}}
implementación
mangosta
Puede especificarlo en un esquema de mangosta:
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"}}
}
}
});
o agregarlo directamente a la colección (que usa el controlador nativo node.js):
User.collection.createIndex("email", {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
});
driver nativo mongodb
utilizando collection.createIndex
db.collection('users').createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
},
function (err, results) {
// ...
}
);
cáscara de mongodb
usando db.collection.createIndex:
db.users.createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {$type: "string"}
}
})
Esto permitirá insertar varios registros con un nullcorreo electrónico, o sin ningún campo de correo electrónico, pero no con la misma cadena de correo electrónico.