tl; dr
Да, возможно иметь несколько документов с полем, установленным на null
или не определенным, при одновременном применении уникальных «фактических» значений.
требования :
- MongoDB v3.2 +.
- Знание ваших конкретных типов значений заранее (например, всегда
string
или object
, когда не null
).
Если вы не заинтересованыне стесняйтесь переходить к разделу implementation
.
более длинная версия
Чтобы дополнить ответ @ Nolan, начиная с MongoDB v3.2, вы можете использовать частичный уникальный индекс свыражение фильтра.
Частичное выражение фильтра имеет ограничения.Он может включать только следующее:
- выражения равенства (т. Е. Field: value или с использованием оператора
$eq
), $exists: true
выражение, $gt
, $gte
, $lt
, $lte
выражений, $type
выражений, $and
оператор только на верхнем уровне
Это означает, что тривиальное выражение {"yourField"{$ne: null}}
нельзя использовать.
Однако, если ваше поле всегда использует один и тот же тип , вы можете использовать $type
выражение .
{ 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"]}}
реализация
mongoose
Вы можете сpecify его в схеме 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"}}
}
}
});
или напрямую добавьте его в коллекцию (которая использует собственный драйвер 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"}
}
})
Thisпозволит вставлять несколько записей с null
электронной почтой или без поля электронной почты вообще, но не с одной и той же строкой электронной почты.