$ lookup с вложенными документами - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть три коллекции, которые мне нужно присоединить / посмотреть."Группы" "Пользователи" "LinkedTags" "Фотографии"

Я получаю все группы из групп сбора.

group {
    id: 1,
    start: 10.12,
    linkedUsers : [1,2,3,4,5]
}

Затем мне нужно искать / присоединяться от пользователей

user {
    id: 1,
    name: ""
}

Затем из связанных тегов

tag {
    userId: 1,
    rounds: 3,
    time: 180
}

Затем из "фотографий"

photo {
    userId: 1,
    location: ""
}

Так что мне нужно, чтобы это было:

Group {
    id: 1,
    start: 10.12,
    linkedUsers: [1,2,3,4],
    users: [
        1:{
            id: 1,
            name: "",
            rounds: 3,
            time: 180,
            photos: [
                1: {
                    id: 1,
                    location: ""
                }
            ]
        }
    ]
}

Вот чтоЯ пытался до сих пор.Я думаю, что мне нужно сделать это поэтапно, но я не понял, как это сделать.

  db('groups').aggregate([
    {
      $lookup: {
        from: 'users',
        localField: 'linkedUsers',
        foreignField: 'id',
        as: 'users'
      }
    },
    {
      $unwind: "$users"
    },
    {
      $lookup: {
        from: 'photos',
        localField: 'linkedUsers',
        foreignField: 'id',
        as: 'photos'
      }
    },
    {
      $unwind: "$photos"
    },
    {
      $lookup: {
        from: 'linkedTags',
        localField: 'linkedUsers',
        foreignField: 'id',
        as: 'tags'
      }
    },
    {
      $unwind: "$tags"
    },
    { $group: {
        _id: null,
        id: "$id",
        start: '$start',
        linkedUsers: "$linkedUsers",
        users: {$push: {
          id: "$users.id",
          name: "$users.name",
          rounds: "$tags.rounds",
          time: "$tags.time",
          photos: {$push: {
            id: "$photos.id",
            location: "photos.location"
          }}
        }}
    }}
  ])

РЕДАКТИРОВАТЬ 1: Это первая ошибка, с которой я сталкиваюсь:

MongoError: Поле 'id' должно быть объектом-аккумулятором

Я прочитал об этом, но не понимаю, как все это сочетается.

Редактировать 2: Я исправил это, заключив группу в _id: {}

Теперь я сталкиваюсь с нераспознанным выражением '$ push'

Редактировать 3: Выполняетсяна Atlas, 4.0.4 Enterprise.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

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

db.group.aggregate([
  { "$lookup": {
    "from": "users",
    "let": { "linkedUsers": "$linkedUsers" },
    "pipeline": [
      { "$match": { "$expr": { "$in": ["$_id", "$$linkedUsers"] } } },
      { "$lookup": {
        "from": "tags",
        "let": { "userId": "$_id" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": ["$userId", "$$userId"] } } }
        ],
        "as": "tags"
      }},
      { "$lookup": {
        "from": "photos",
        "let": { "userId": "$_id" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": ["$userId", "$$userId"] } } }
        ],
        "as": "photos"
      }}
    ],
    "as": "linkedUsers"
  }}
])

Редактировать: Удалено пустое пространство в переменных

0 голосов
/ 27 ноября 2018

Я попытался создать один пример данных дампа отношения

Проверить рабочий пример здесь

Попробуйте сгруппировать по _id и просто назначить photos: $photos.

Второй уровень $push был проблемой в вашем случае.

db.groups.aggregate([
  {
    $unwind: "$linkedUsers"
  },
  {
    $lookup: {
      from: "users",
      localField: "linkedUsers",
      foreignField: "_id",
      as: "users"
    }
  },
  {
    $unwind: "$users"
  },
  {
    $lookup: {
      from: "photos",
      localField: "linkedUsers",
      foreignField: "userId",
      as: "photos"
    }
  },
  {
    $unwind: "$photos"
  },
  {
    $lookup: {
      from: "tags",
      localField: "linkedUsers",
      foreignField: "userId",
      as: "tags"
    }
  },
  {
    $unwind: "$tags"
  },
  {
    $group: {
      _id: "$_id",
      "start": {
        $first: "$start"
      },
      "linkedUsers": {
        $first: "$linkedUsers"
      },
      "users": {
        "$push": {
          "id": "$users._id",
          "name": "$users.name",
          "rounds": "$tags.rounds",
          "time": "$tags.time",
          "photos": "$photos"
        }
      }
    }
  }
])

Поскольку я создал ручные данные, вам может понадобиться ключили изменение имени БД в вашей реализации.

ПРИМЕЧАНИЕ: -

Я рекомендовал использовать preserveNullAndEmptyArrays при использовании многоуровневого $unwind.С помощью которого можно получить оригинальный документ, если внутренний уровень не найден.

{ $unwind: { path: "$tags", preserveNullAndEmptyArrays: true } } 

Надеюсь, это поможет вам.

...