MongoDB: вложенная агрегация

#javascript #mongodb #mongoose #nosql

#javascript #mongodb #мангуст #nosql

Вопрос:

У меня есть несколько коллекций:

пользователи — схема сбора

История — это вложенный документ коллекции / документа пользователя

 name: "jacob"
_id: 5fc53209e70f776378cce0c5,
history: [
  {
     _id: 5fc634bee65f96338a63b9e4,
     article: 5fc5f3e6140646c2024f7963,
     created_at: 2010-12-01T12:19:10.121 00:00
  },
  {
    _id: 5fc634d8e65f96338a63b9e5,
    article: 5fc5faaa8b1fffc1f4dec900,
    created_at: 2010-12-01T12:19:36.102 00:00
  }
]
 

статьи — схема сбора

 {
   _id: 5fc5faaa8b1fffc1f4dec900,
   title: "hello there",
   author: 5fc531cae70f776378cce0c4 // Author is related to user collection
},
{
   _id: 5fc5f3e6140646c2024f7963,
   title: "hello wonderland",
   author: 5fc531cae70f776378cce0c4 // Author is related to user collection
}
 

Возможно ли, чтобы $lookup статья в истории, а затем $lookup автор статьи? А также сортировать по дате истории?

Желаемый результат

 ...
name: "jacob",
_id: 5fc53209e70f776378cce0c5,
history: [
  {
     _id: 5fc634bee65f96338a63b9e4,
     article: {
        _id: 5fc5faaa8b1fffc1f4dec900,
        title: "hello there",
        author: {
           _id: 5fc531cae70f776378cce0c4,
           name: "melissa"
        }
     },
     created_at: 2010-12-01T12:19:10.121 00:00
  },
  {
    _id: 5fc634d8e65f96338a63b9e5,
    article: {
       _id: 5fc5faaa8b1fffc1f4dec900,
       title: "hello wonderland",
       author: {
          _id: 5fc531cae70f776378ccedsu8,
         name: "omelia",
       }
    },
    created_at: 2010-11-12T2:19:36.102 00:00
  }
]
 

ПРИМЕЧАНИЕ: Сортировка по дате в порядке убывания

Ответ №1:

Вы можете попробовать,

  • $unwind деконструировать history массив
  • $lookup присоединяйтесь к коллекции статей, разрешите передать идентификатор статьи,
    • $match чтобы соответствовать идентификатору статьи
    • $lookup для объединения с коллекцией пользователей
    • $unwind деконструировать пользователей, потому что его массив
    • $project для отображения обязательных полей
  • $unwind деконструировать массив статей
  • $sort по created_at дате
  • $group по идентификатору и реконструировать history массив
 db.users.aggregate([
  { $unwind: "$history" },
  {
    $lookup: {
      from: "articles",
      let: { articleId: "$history.article" },
      pipeline: [
        { $match: { $expr: { $eq: ["$_id", "$articleId"] } } },
        {
          $lookup: {
            from: "users",
            localField: "author",
            foreignField: "_id",
            as: "author"
          }
        },
        { $unwind: "$author" },
        {
          $project: {
            _id: 1,
            author: { _id: 1, name: 1 },
            title: 1
          }
        }
      ],
      as: "history.article"
    }
  },
  { $unwind: "$history.article" },
  { $sort: { "history.created_at": -1 } },
  {
    $group: {
      _id: "$_id",
      history: { $push: "$history" },
      name: { $first: "$name" }
    }
  }
])
 

Игровая площадка