3

我有这样的comment收藏

{
  _id: 'c1',
  text: 'comment 1',
  votes: 1,
  replies: [
    {
      _id: 'r1',
      text: 'reply 1',
      isReply: true,
      votes: 3
    },
    {
      _id: 'r2',
      text: 'reply 2',
      isReply: true,
      votes: 0
    }
  ]
},
{
  _id: 'c2',
  text: 'comment2',
  votes: 2,
  replies: []
}

这个想法是一个评论可以有很多回复。所有评论和回复都有id , text , votes。我怎样才能获得最好的 2 条评论或获得最多票数的回复。在给定的情况下,这将是“回复 1”和“评论 2”。

我可以向 mongodb 发送 1 个请求以获得最好的 2 个评论,另一个请求获得最好的 2 个回复,然后比较它们以获得我想要的。

但是,只有 1 个对 mongodb 的请求是否有可能,我可以得到这样的结果?

 [
   {
     _id: 'r1',
     text: 'reply 1',
     isReply: true,
     votes: 3
   },
   {
     _id: 'c2',
     text: 'comment 2',
     votes: 2
   }
 ]

或者更好的是,我可以将评论/回复展平以得到按排序的评论或回复列表votes?在这种情况下,它将是 [r1, c2, c1, r2] 分别具有它们的属性

谢谢。


更新:我试过aggregate({$unwind: '$replies'})了,但我仍然有 2 个不同级别的评论和回复,我无法通过使用聚合框架进行比较。也许有办法使这两个级别变平,我对 mongodb 很陌生。

4

2 回答 2

4

对模式进行一些改变以使投票非规范化将使排序更容易。如果评论文档中嵌入了另一个投票数组,例如:

votes: [ 
  { "type" : "c", "_id": "c1", v: 1},
  { "type" : "r", "_id": "r1", v: 3},
  { "type" : "r", "_id": "r2", v: 2}
]

查询和排序可能是直截了当的。

db.playground.aggregate(
[
  {$project: { votes: 1 }},
  {$unwind: "$votes"},
  {$sort: {"votes.v": -1}},
  {$limit: 2}
])

它给出了以下结果。

{
  "result" : [
    {
      "_id" : "c1",
      "votes" : {
        "type" : "c",
        "_id" : "c1",
        "v" : 3
      }
    },
    {
      "_id" : "c1",
      "votes" : {
        "type" : "r",
        "_id" : "r1",
        "v" : 2
      }
    }
  ],
  "ok" : 1
}

需要在 votes.v 上建立索引,因为它看起来像是一个阅读量很大的用例。更新评论时,只需在同一更新请求中更新投票数组。

于 2013-09-16T16:30:23.180 回答
0

我建议您不要将回复放在评论对象中。DbObject 的最大大小为 16mb。如果一个评论得到很多回复,这个结构就会失败。而不是这种结构,您可以将回复保留在评论集合中并将父评论 id 放入回复对象(您可能希望放置像 {type: 'reply'} 或 {type: 'comment'} 这样的字段,但 parentCommentId 的存在将提供哪个是什么类型)。通过这种方式,您可以轻松查询评论和回复。

我还想补充一点,聚合查询不利于 UI 响应。我不知道你的用例,但不要忘记它。

于 2013-09-16T15:00:03.050 回答