tl; dr
Sim, é possível ter vários documentos com um campo definido como null
ou não definido, enquanto impõe valores "reais" exclusivos.
requisitos :
- MongoDB v3.2 +.
- Conhecer com antecedência o (s) seu (s) tipo (s) de valor concreto (por exemplo, sempre a
string
ou object
quando não null
).
Se você não estiver interessado nos detalhes, sinta-se à vontade para pular para a implementation
seção.
versão mais longa
Para complementar a resposta de @Nolan, começando com MongoDB v3.2, você pode usar um índice exclusivo parcial com uma expressão de filtro.
A expressão de filtro parcial tem limitações. Só pode incluir o seguinte:
- expressões de igualdade (ou seja, campo: valor ou usando o
$eq
operador),
$exists: true
expressão,
$gt
, $gte
, $lt
, $lte
Expressões,
$type
expressões,
$and
operador apenas no nível superior
Isso significa que a expressão trivial {"yourField"{$ne: null}}
não pode ser usada.
No entanto, supondo que seu campo sempre use o mesmo tipo , você pode usar uma $type
expressão .
{ field: { $type: <BSON type number> | <String alias> } }
MongoDB v3.6 adicionou suporte para especificar vários tipos possíveis, que podem ser passados como uma matriz:
{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }
o que significa que permite que o valor seja de vários tipos, quando não null
.
Portanto, se quisermos permitir que o email
campo no exemplo abaixo aceite um string
ou, digamos, binary data
valores, uma $type
expressão apropriada seria:
{email: {$type: ["string", "binData"]}}
implementação
mangusto
Você pode especificá-lo em um esquema mongoose:
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"}}
}
}
});
ou adicione-o diretamente à coleção (que usa o driver node.js nativo):
User.collection.createIndex("email", {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
});
driver mongodb nativo
usando collection.createIndex
db.collection('users').createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
},
function (err, results) {
// ...
}
);
concha mongodb
usando db.collection.createIndex
:
db.users.createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {$type: "string"}
}
})
Isso permitirá inserir vários registros com um null
e - mail ou sem nenhum campo de e-mail, mas não com a mesma sequência de e-mail.