Получить сообщения с последними комментариями n в MongoDB - PullRequest
0 голосов
/ 10 ноября 2018

Так что это распространенная проблема, получение сообщений с комментариями, которые я не могу решить в MongoDB, в отличие от MySQL, который легко решается с помощью left-join.

Проблема:

Я хотел бы получить последние 8 сообщений с 2 недавними комментариями к каждому сообщению в MongoDB

  • Я не хочу реструктурировать данные поста, чтобы они содержали список соответствующих идентификаторов комментариев, потому что в будущем я буду ожидать тысячи комментариев.

  • Я действительно не хочу прибегать к извлечению постов, а затем выполнить 8 отдельных запросов, используя идентификатор поста, чтобы найти 2 последних комментария. ( хотя я думаю, что это следующее лучшее решение )

  • Я попытался установить postSchema.virtual('comments', ..), а затем при выполнении запроса, заполнив его с помощью Post.find(..).populate('comments', options: {limit: 2}), но, к сожалению, предел возвращает противоречивые результаты .

Данные:

Post:
{ body: "post1" }
{ body: "post2" }
{ body: "post3" }
...
{ body: "post8" }

Comment:
{ post_id: 1, message: "comment1" }
{ post_id: 2, message: "comment2" }
{ post_id: 2, message: "comment3" }
{ post_id: 3, message: "comment4" }

Все документы имеют поле date, но удалены из-за краткости

Ожидаемый результат:

{ 
  body:"post1", 
  comments: [
    { post_id: 1, message: "comment1" }
  ]
}
{ 
  body:"post2", 
  comments: [
    { post_id: 2, message: "comment2" },
    { post_id: 2, message: "comment3" }
  ]
}
{ 
  body:"post3", 
  comments: [
    { post_id: 3, message: "comment4" }
  ]
}
...

1 Ответ

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

Если вы используете MongoDB 3.6 или выше, вы можете использовать $ lookup с пользовательским конвейером , чтобы "объединить" посты с комментариями и взять 2 самых последних (используя $ limit )

db.posts.aggregate([
    {
        $sort: { date: -1 }
    },
    {
        $limit: 8
    },
    {
        $lookup: {
            from: "comments",
            let: { postId: "$_id" },
            pipeline: [
                { $match: { $expr: { $eq: [ "$$postId", "$post_id" ] } } },
                { $sort: { date: -1 } },
                { $limit: 2 }
            ],
            as: "comments"
        }
    }
])
...