MongoDB: Ссылка на другой документ с дополнительной информацией
У меня есть ситуация, когда у меня есть тип группового документа. Я хочу, чтобы поле со списком содержало ссылочный идентификатор для пользователей в группе. Однако мне нужно указать, какие пользователи имеют доступ администратора. Должен ли я иметь два списка, один из которых является обычным пользователем и одним из администраторов, или иметь собственный документ, в который я встраиваю список, в котором просто есть ссылочный идентификатор и значение bool? В основном это много ко многим, поскольку оба документа имеют список идентификаторов ссылок на другие документы. Я просто не уверен, как включить это другое значение.
Если это имеет какое-то значение, я использую Python/Mongoengine для доступа к MongoDB
1 ответ
Существуют различные способы моделирования вашего требования в текущей форме. Я попытаюсь показать вам один такой способ и использует $ lookup. Вы должны попробовать две отдельные коллекции, по одной для каждой группы и пользователей, как показано ниже.
Еще одним вариантом будет использование $DBRef, который будет загружать всех пользователей в группе, когда вы выбираете коллекцию группы. Эта опция будет зависеть от драйвера Python, и я уверен, что драйвер поддерживает это.
Документ группы
{
"_id": ObjectId("5857e7d5aceaaa5d2254aea2"),
"name": "newGroup",
"usersId": ["user1", "user2"]
}
Документ пользователя
{ "_id" : "user1", "isAdmin" : true }
{ "_id" : "user2" }
Получить всех пользователей в группе
db.groups.aggregate({
$unwind: '$usersId'
}, {
$lookup: {
from: "users",
localField: "usersId",
foreignField: "_id",
as: "group_users"
}
})
отклик
{
"_id": ObjectId("5857e7d5aceaaa5d2254aea2"),
"name": "newGroup",
"usersId": "user1",
"group_users": [{
"_id": "user1",
"isAdmin": true
}]
} {
"_id": ObjectId("5857e7d5aceaaa5d2254aea2"),
"name": "newGroup",
"usersId": "user2",
"group_users": [{
"_id": "user2"
}]
}
Получить всех администраторов в группе
db.groups.aggregate({
$unwind: '$usersId'
}, {
$lookup: {
from: "users",
localField: "usersId",
foreignField: "_id",
as: "group_users"
}
}, {
$match: {
"group_users.isAdmin": {
$exists: true
}
}
})
отклик
{
"_id": ObjectId("5857e7d5aceaaa5d2254aea2"),
"name": "newGroup",
"usersId": "user1",
"group_users": [{
"_id": "user1",
"isAdmin": true
}]
}
На основании комментария:
Администратор является администратором для группы, поэтому я не могу сохранить его в таблице пользователей. Это отношения многие ко многим.
Я думаю, что вы должны включить как список обычных пользователей, так и список администраторов. Это будет использовать добавленные вами индексы и сделает ваши запросы на чтение действительно простыми.
Документ группы
{ "_id" : "newGroup", "userIds" : [ "user1" ], "adminIds" : [ "user2" ] }
Документ пользователя
{ "_id" : "user1", "groupIds" : [ "newGroup" ] } -- regular user in newGroup
{ "_id" : "user2", "groupIds" : [ "newGroup" ] } -- admin user in newGroup.
{ "_id" : "user3", "groupIds" : [ ] }
Получить всех постоянных пользователей
db.groups.aggregate({
$unwind: '$userIds'
}, {
$lookup: {
from: "users",
localField: "userIds",
foreignField: "_id",
as: "group_users"
}
})
Получить всех администраторов
db.groups.aggregate({
$unwind: '$adminIds'
}, {
$lookup: {
from: "users",
localField: "adminIds",
foreignField: "_id",
as: "group_users"
}
})