tl; dr
Sí, es posible tener varios documentos con un campo configurado null
o no definido, mientras se aplican valores "reales" únicos.
requisitos :
- MongoDB v3.2 +.
- Conocer sus tipos de valores concretos de antemano (por ejemplo, siempre a
string
o object
cuándo no null
).
Si no está interesado en los detalles, no dude en pasar a la implementation
secció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
$eq
operador),
$exists: true
expresión,
$gt
, $gte
, $lt
, $lte
Expresiones,
$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 $type
expresió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 email
campo del ejemplo siguiente acepte valores string
o, digamos binary data
, una $type
expresió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 null
correo electrónico, o sin ningún campo de correo electrónico, pero no con la misma cadena de correo electrónico.