У меня есть требование обеспечить уникальность документов в коллекции 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"}
Можно ли реализовать это в самой базе данных, а не в логике приложения?
Да, это то, что я использую. Спасибо за указание - я не видел этого тега в списке. Поскольку я могу использовать большую часть документации MongoDB как есть, я пометил ее тегом mongo-db.
Я думаю, что невозможно «обеспечить соблюдение» правила с существующими данными только с помощью базы данных. Возможно, вам придется выполнить единоразовую очистку, если у вас есть данные, которые нарушают правило. Однако для вновь вставленных документов вы можете выполнить следующие действия и объединить их в коллекцию.
$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
Спасибо за ответ. Для меня это имеет смысл. Я верю в "coll": "collection"
, мы принимаем во внимание имеющиеся в коллекции документы? Кроме того, при этом кто-то все еще может писать код для вставки документов без этой логики. Можно ли каким-то образом запустить эту логику каждый раз, когда документы добавляются в эту коллекцию?
@ksceriath Как я уже упоминал, я не думаю, что существует способ обеспечить соблюдение правила для каждой вставки только с помощью средств базы данных. На самом деле я рассмотрел триггеры и потоки изменений, но они включают в себя определенную часть кода приложения. Я предлагаю вам использовать приведенное выше решение как единственный способ вставки, если это возможно. Например, вы можете обернуть это как единый API вставки и представить его только как средство вставки данных в базу данных.
@ksceriath и насчет "coll": "collection"
, да, просто замените его на название вашей коллекции.
Почему вы отметили тегами CosmosDB и MongoDB? Стоит ли отмечать
azure-cosmosdb-mongoapi
? Это то, что вы на самом деле используете?