У меня есть требование обеспечить уникальность документов в коллекции MongoDB.
В моих документах есть поле «id», поле «имя», а также несколько других полей. Поле «id» НЕ уникально.
Мое требование таково, что «имя» должно быть уникальным для разных значений «id». Однако может существовать несколько документов с одним и тем же «идентификатором» и одним и тем же «именем». (В одном и том же «id» может быть несколько «имен»).
Например:
Разрешены следующие документы (один и тот же идентификатор, одинаковые/разные имена):
{ "id" : "1", "name": "Alice"}
{ "id" : "1", "name": "Bob"}
{ "id" : "1", "name": "Alice"}
Однако следующее не разрешено (то же имя, разные идентификаторы):
{ "id" : "1", "name": "Alice"}
{ "id" : "2", "name": "Alice"}
Можно ли реализовать это в самой базе данных, а не в логике приложения?
Я думаю, что невозможно «обеспечить соблюдение» правила с существующими данными только с помощью базы данных. Возможно, вам придется выполнить единоразовую очистку, если у вас есть данные, которые нарушают правило. Однако для вновь вставленных документов вы можете выполнить следующие действия и объединить их в коллекцию.
$unionWith
новые документы, которые вы хотели вставить (вставив их $documents
$setWindowFields
для вычисления $denseRank
внутри раздела name
и в порядке id
$match
выбрать только документы с рангом: 1$unset
поле ранга$merge
в коллекциюdb.collection.aggregate([
{
"$unionWith": {
"coll": "collection",
"pipeline": [
{
"$documents": [
// documents to be inserted here
{
"id": "1",
"name": "Alice"
}
]
}
]
}
},
{
"$setWindowFields": {
"partitionBy": "$name",
"sortBy": {
"id": 1
},
"output": {
"idRankInName": {
"$denseRank": {}
}
}
}
},
{
"$match": {
"idRankInName": 1
}
},
{
"$unset": "idRankInName"
},
{
"$merge": {
"into": "collection"
}
}
])
Mongo Playground для случаев 1 и 2
Игровая площадка Mongo для случая 3