【问题标题】:|MongoDB| How to sort and limit embedded arrays? embedded array pagination|MongoDB|如何对嵌入式数组进行排序和限制?嵌入式数组分页
【发布时间】:2013-11-10 14:44:49
【问题描述】:

我很难在 mongodb 中对嵌入数组的结果进行排序和限制。这是场景:

我有一个 post-comment 结构,其中 post 包含一个 cmets 数组。我想获得一个 cmets 列表,按 createdAt 排序并做一个限制/偏移量......就像给定一个帖子 id 对 cme​​ts 进行分页并将它们返回给我。 =]

...下面是结构示例:

{    "_id" : ObjectId("52707a234f2044b7f2d22083"),
     "comments" : [{
            "_id" : ObjectId("5270986b4f204f5dd51ada8a"),
            "comment" : "asdfasdf asdfasdfa ",
            "userid" : NumberLong(1),
            "likes" : [ ],
            "createdAt" : ISODate("2013-10-30T05:26:03.858Z")},
           {
            "_id" : ObjectId("527098714f204f5dd51ada8b"),
            "comment" : "asdfasdf asdfasdfa ",
            "userid" : NumberLong(1),
            "likes" : [ ],
            "createdAt" : ISODate("2013-10-30T05:26:09.425Z")
           }
    ],
    "createdAt" : ISODate("2013-10-30T03:16:51.745Z"),
    "likes" : [ ],
    "status" : "simbora!!",
    "userid" : NumberLong(1)
}

所以...我可以试试这个查询:

db.post.aggregate([ 
{$match: {_id: new ObjectId("52707a234f2044b7f2d22083")}}, 
{$unwind: "$comments"}, 
{$sort: {"comments.createdAt": -1}},
{$limit: 2}
]);

它给了我这个:

"result" : [
        {
                "_class" : "models.documents.Post",
                "_id" : ObjectId("52707a234f2044b7f2d22083"),
                "comments" : {
                        "_id" : ObjectId("527098714f204f5dd51ada8b"),
                        "comment" : "asdfasdf asdfasdfa ",
                        "userid" : NumberLong(1),
                        "likes" : [ ],
                        "createdAt" : ISODate("2013-10-30T05:26:09.425Z")
                },
                "createdAt" : ISODate("2013-10-30T03:16:51.745Z"),
                "likes" : [ ],
                "status" : "simbora!!",
                "userid" : NumberLong(1)
        },
        {
                "_class" : "models.documents.Post",
                "_id" : ObjectId("52707a234f2044b7f2d22083"),
                "comments" : {
                        "_id" : ObjectId("5270986b4f204f5dd51ada8a"),
                        "comment" : "asdfasdf asdfasdfa ",
                        "userid" : NumberLong(1),
                        "likes" : [ ],
                        "createdAt" : ISODate("2013-10-30T05:26:03.858Z")
                },
                "createdAt" : ISODate("2013-10-30T03:16:51.745Z"),
                "likes" : [ ],
                "status" : "simbora!!",
                "userid" : NumberLong(1)
        }
],
"ok" : 1

请注意,cmets 不再是一个数组,而是一个对象……虽然它给了我有序和有限的集合,但它也给了我每条评论的父对象……那不太好。所以我尝试了这个:

db.post.aggregate([
{$match: {_id: new ObjectId("52707a234f2044b7f2d22083")}},
{$unwind: "$comments"},
{$sort: {"comments.createdAt": -1}},
{"$project": {"_id": 0, "comments": "$comments"}},
{"$group": {"_id": "$_id", "comments": {"$push": "$comments"}}},
]);

它给了我这个:

{
        "result" : [
                {
                        "_id" : null,
                        "comments" : [
                                {
                                        "_id" : ObjectId("527098714f204f5dd51ada8b"),
                                        "comment" : "asdfasdf asdfasdfa ",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:26:09.425Z")
                                },
                                {
                                        "_id" : ObjectId("5270986b4f204f5dd51ada8a"),
                                        "comment" : "asdfasdf asdfasdfa ",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:26:03.858Z")
                                },
                                {
                                        "_id" : ObjectId("527098694f204f5dd51ada89"),
                                        "comment" : "asdfasdf asdfasdfa ",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:26:01.174Z")
                                },
                                {
                                        "_id" : ObjectId("527098674f204f5dd51ada88"),
                                        "comment" : "asdfasdf asdfasdfa ",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:25:59.795Z")
                                },
                                {
                                        "_id" : ObjectId("527098644f204f5dd51ada87"),
                                        "comment" : "asdfasdf asdfasdfa ",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:25:56.936Z")
                                },
                                {
                                        "_id" : ObjectId("527098604f204f5dd51ada86"),
                                        "comment" : "asdfasdf asdfasdfa ",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:25:52.379Z")
                                },
                                {
                                        "_id" : ObjectId("52707a234f2044b7f2d22083"),
                                        "comment" : "asdfasdf asdfasdfa ",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:24:36.539Z")
                                },
                                {
                                        "_id" : null,
                                        "comment" : "bla bla",
                                        "userid" : NumberLong(1),
                                        "likes" : [ ],
                                        "createdAt" : ISODate("2013-10-30T05:23:24.037Z")
                                }
                        ]
                }
        ],
        "ok" : 1
}

这也不是很好,因为如果我应用限制并跳过运算符,它将通过帖子进行限制,而不是评论......

谁能帮帮我??

【问题讨论】:

  • 如果你想审查你的代码,你应该去 codereview.stackexchange.com/‎

标签: arrays mongodb sorting


【解决方案1】:

如果我理解,您想通过 id 查找帖子并仅返回最后 2 个 cmets。

到目前为止,您还没有,解决方案是您的 2 次试验的组合:

db.posts.aggregate( 
  {$match: {_id: new ObjectId("52707a234f2044b7f2d22083")}}, 
  {$unwind: "$comments"}, 
  {$sort: {"comments.createdAt": -1}},
  {$limit: 2},
  {"$group": {"_id": "$_id", "comments": {"$push": "$comments"}}}
)

【讨论】:

  • 感谢您的反馈。问题是,我需要对 cme​​ts 数组进行分页......像这样: db.post.aggregate([ {$match: {_id: new ObjectId("52707a234f2044b7f2d22083")}}, {$unwind: "$cmets" }, {$sort: {"cmets.createdAt": -1}}, {$limit: 2}, {$skip: 2}, {"$group": {"_id": "$_id", "cmets ": {"$push": "$cmets"}}} ]);问题是,当我添加 {$skip: 2} 操作时,我希望跳过第一个并获得下一个 2 ......但事实并非如此......相反我得到一个空的结果。但如果我这样做 {$limit: 4},{$skip: 2} 比我得到正确的结果。奇数
  • 所以我正在阅读有关我的问题的更多信息,我发现了这个线程:stackoverflow.com/questions/10424403/…。有人同意吗?谢谢。
  • @MisaelNeto 没办法!把cmets放到另外一个文件里就是用一个NoSQL作为关系数据库!在非关系数据库中创建引用是没有意义的。
猜你喜欢
  • 2012-05-12
  • 1970-01-01
  • 2019-02-14
  • 2021-03-24
  • 2016-09-23
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2016-10-26
相关资源
最近更新 更多