Условный $ lookup в MongoDB? - PullRequest
       3

Условный $ lookup в MongoDB?

0 голосов
/ 10 декабря 2018

У меня есть две коллекции в MongoDB 3.6:

users: [
  {name: "John", allowedRoles: [1, 2, 3]},
  {name: "Charles", allowedRoles: [1]},
  {name: "Sarah", isAdmin: true}
]

roles: [
  {_id: 1, name: "Foo", description: "This role allows to foo the blargs"},
  {_id: 2, name: "Bar", description: "..."},
  {_id: 3, name: "Doh", descripcion: "..."}
]

Я очень плохо знаком с MongoDB;Я только что понял, как запросить пользователя и объединить все данные из его ролей, используя $lookup этап агрегирования:

db.users.aggregate([{
  "$match": { "name": "John" }          // Or without this $match part, to get all users
},{                                     //
  "$lookup": {
    "from": "roles",
    "localField": "allowedRoles",
    "foreignField": "_id",
    "as": "roles"
  }
}]);

Это работает длямои постоянные пользователи, у которых есть массив идентификаторов разрешенных ролей.У меня также есть пользователи-администраторы, которые могут получить доступ ко всем существующим ролям, но не имеют массива allowedRoles (это было бы бременем для обслуживания, так как новые роли будут создаваться часто).Поэтому вместо указания полей соединения я делаю $lookup с пустым конвейером, чтобы получить декартово произведение обеих коллекций:

db.users.aggregate([{
  "$match": { "name": "Sarah" }
},{
  "$lookup": {
    "from": "roles",
    "pipeline": [],
    "as": "roles"
  }
}]);

Есть ли способ получить оба, содин запрос? с условным выражением или чем-то?

В базе данных SQL я бы просто включил условие в объединение:

select users.*, roles.*
from users
left join users_x_roles inter on users.id = inter.user_id
left join roles on inter.role_id = roles.id or users.is_admin = 1;
--                                          ^^^^^^^^^^^^^^^^^^^^^

1 Ответ

0 голосов
/ 10 декабря 2018

Вы можете использовать агрегацию ниже

$expr позволяет использовать оператор агрегирования внутри него.Таким образом, вы можете легко использовать агрегацию $cond для пользователей, у которых allowedRoles, а у кого нет

db.users.aggregate([
  { "$match": { "name": "Charles" }},
  { "$lookup": {
    "from": "roles",
    "let": { "ar": "$allowedRoles" },
    "pipeline": [
      { "$match": {
        "$expr": {
          "$cond": [
            { "$eq": [{ "$type": "$$ar" }, "missing"] },
            {},
            { "$in": ["$_id", "$$ar"] }
          ]
        }
      }}
    ],
    "as": "roles"
  }}
])
...