在MongoDB中对子文档进行排序

时间:2010-10-03 06:17:58

标签: sorting mongodb document

有没有办法在mongo查询中对子文档进行排序?示例(博客集合):

{
    "_id" : ObjectId("4c69d19532f73ad544000001"),
    "content" : "blah blah blah",
        "comments" : {
{"author": "jim",   "content":"comment content 1", "date" : "07-24-1995"},
{"author": "joe",   "content":"comment content 2",  "date" : "07-24-1996"}
{"author": "amy", "content":"comment content 3", "date" : "09-10-1999"}
        }
}
{
    "_id" : ObjectId("4c69d19532f73ad544000002"),
    "content" : "blah blah blah",
        "comments" : {
{"author": "jim",   "content":"comment content 1",  "date" : "07-24-1995"},
{"author": "joe",   "content":"comment content 2",  "date" : "07-24-1996"}
{"author": "amy", "content":"comment content 3",  "date" : "07-24-1997"}
        }
}

我希望以我的方式订购我的博客文章,然后在我的博客帖子中通过按日期的反向排序或我想要的任何其他排序来订购评论。这可能与mongoDB有关吗?

5 个答案:

答案 0 :(得分:4)

在mongo 2.4或更高版本中,您可以在更新时使用$ sort。 新修改器允许您对子文档进行排序。

更多信息可以阅读此页面, http://docs.mongodb.org/manual/reference/operator/sort/

答案 1 :(得分:1)

不可能直接从MongoDB中删除,但是当您拉动文档时,您可以使用您的语言所使用的任何本机排序方法对数组进行排序,就像它是一个对象数组一样。这是我在MongoDB博客上发表评论的方式。

PHP代码

/* Takes an array of comments and turns them into native objects */
public static function loadMany($pcomments)
{
    $comments = array();
    if(isset($pcomments) && count($pcomments) > 0)
    {
        foreach($pcomments as $key => $comment)
        {
            $comment['data']['index'] = $key;
            $comments[] = Comment::loadOne($comment['data']);
        }
    }
    usort($comments, "comment_compare");
    return $comments;
}

/* Compares comment timestamps */
function comment_compare($a, $b)
{
    if($a->timestamp->sec == $b->timestamp->sec)
    {
        return 0;
    }
    return ($a->timestamp->sec < $b->timestamp->sec) ? -1 : 1;
}

答案 2 :(得分:0)

我认为你不能。我在forums上提出了同样的问题。

答案 3 :(得分:0)

Mongo 4.4开始,$function聚合运算符允许应用自定义javascript函数来实现MongoDB查询语言不支持的行为。

例如,为了按照对象的字段之一对数组进行排序:

// {
//   "content": "blah blah blah",
//   "comments": [
//     { "author": "jim", "content": "comment content 1", "date": "07-24-1995" },
//     { "author": "joe", "content": "comment content 2", "date": "07-24-1996" },
//     { "author": "amy", "content": "comment content 3", "date": "09-10-1999" }
//   ]
// }
db.collection.aggregate(
  { $sort: { content: 1 } }, // or whatever sort order
  { $set:
    { "comments":
      { $function: {
          body: function(comments) {
            return comments.sort((a, b) => a.date < b.date);
          },
          args: ["$comments"],
          lang: "js"
      }}
    }
  }
)
// {
//   "content": "blah blah blah",
//   "comments": [
//     { "author": "amy", "content": "comment content 3", "date": "09-10-1999" },
//     { "author": "joe", "content": "comment content 2", "date": "07-24-1996" },
//     { "author": "jim", "content": "comment content 1", "date": "07-24-1995" }
//   ]
// }

$function具有3个参数:

  • body,这是要应用的函数,其参数是要修改的数组。
  • args,其中包含body函数作为参数的记录中的字段。在我们的情况下,"$comments"
  • lang,这是编写body函数的语言。当前仅js可用。

答案 4 :(得分:0)

当按序列$unwind> $sort> $group专用于数组时,

db.collection.aggregate([
  { $unwind: "$comments" },
  • $addFieldsdate添加新字段,该字段为字符串,我们需要将其转换为ISO日期以进行正确排序,使用$dateFromString将字符串日期转换为ISO日期
  {
    $addFields: {
      "comments.dateISO": {
        $dateFromString: {
          dateString: "$comments.date",
          format: "%m-%d-%Y"
        }
      }
    }
  },
  • $sort comments.dateISO(-1)降序
  { $sort: { "comments.dateISO": -1 } },
  • $group_id,并使用comments对象重建$push数组,而其他字段仍使用$first
  {
    $group: {
      _id: "$_id",
      comment: { $first: "$comment" },
      comments: { $push: "$comments" }
    }
  }
])

Playground