Как сопоставить команды по свойству лидера, в MongoDB - PullRequest
1 голос
/ 25 июня 2019

У меня есть база данных с некоторыми пользователями, которые принадлежат к командам.У каждой команды есть лидер.У каждого пользователя есть тема.

Я хочу сопоставить команды по теме лидера.

Мои данные выглядят так:

db={
  "teams": [
    {
      _id: "t1",
      members: [
        {
          "_id": "u1",
          "leader": true
        },
        {
          "_id": "u2"
        },
        {
          "_id": "u3"
        }
      ],
    },
    {
      _id: "t2",
      members: [
        {
          "_id": "u2",
          "leader": true
        },
        {
          "_id": "u4"
        }
      ],

    },
    {
      _id: "t3",
      members: [
        {
          "_id": "u1",
          "leader": true
        },
        {
          "_id": "u4"
        }
      ],

    },
    {
      _id: "t4",
      members: [
        {
          "_id": "u2",
          "leader": true
        }
      ],

    },

  ],
  "users": [
    {
      "_id": "u1",
      "subject": "history"
    },
    {
      "_id": "u2",
      "subject": "maths"
    },
    {
      "_id": "u3",
      "subject": "geography"
    },
    {
      "_id": "u4",
      "subject": "french"
    }
  ]
}

Результат, который я хочу получить:

{
    "history": ["t1", "t3"],
    "maths": ["t2", "t4"]
}

У меня есть агрегат, который дает мне _id каждого лидера, и оттуда я могу получить желаемый результат поэтапно, сначала найдя тему каждого лидера, затем вернувшись назад через проекты иназначение темы для каждого проекта на основе определения лидера.Это работает, но это не элегантно, и я думаю, что это будет медленно.Мне кажется, должен быть какой-то лучший способ сделать это, может быть, что-то вроде соединения?

Есть ли отличный способ получить желаемый результат от одной операции MongoDB?

Здесьигровая площадка Монго с моими данными:

https://mongoplayground.net/p/SIJv9-hVNzJ

Большое спасибо за любую помощь.

Редактировать: мои данные теста сбивают с толку, потому что _id используется в обоихколлекции, затрудняя распаковку ответа.Вот обновленная Mongo Playground , которая использует разные имена ключей для каждой коллекции и помогла мне понять идеальный ответ.

1 Ответ

0 голосов
/ 26 июня 2019

Да, вы должны объединить свои коллекции на users._id с $lookup, а затем преобразовать значение в ключ с помощью $arrayToObject (введено в Mongodb 3.4.4)

Вот один из возможных способов сделать это:

db.teams.aggregate([
  {
    "$unwind": "$members"
  },
  {
    "$match": {
      "members.leader": true
    }
  },
  {
    "$lookup": {
      "from": "users",
      "localField": "members._id",
      "foreignField": "_id",
      "as": "users"
    }
  },
  {
    "$unwind": "$users"
  },
  {
    "$group": {
      "_id": "$users.subject",
      "team": {
        "$push": "$_id"
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$arrayToObject": [
          [
            {
              k: "$_id",
              v: "$team"
            }
          ]
        ]
      }
    }
  }
])

попробовать онлайн: mongoplayground.net / p / TuEpMzHkI-0

...