在mongodb php中排序mapReduce结果

时间:2014-04-19 08:36:32

标签: php mongodb

我想对mapReduce函数生成的结果进行排序。 我可以看到有使用

对mapReduce输入进行排序的选项
db.runCommand(
           {
             mapReduce: <collection>,
             map: <function>,
             reduce: <function>,
             out: <output>,
             query: <document>,
             sort: <document>,

           }
         )

虽然我使用上面的命令提供了sort字段,但我的结果没有排序。有或没有排序选项,它产生相同的结果。我可以通过使用 out:&#34; collection&#34; 创建新集合并对其进行排序,但我不想创建中间集合,我希望我的输出为< strong>内联(out:{inline:1})。

我有一个名为帖子的集合。 例如:

{
   postID:1,
   userID:10000001,
   title:"1st Post",
   text:"I this is first post in this collection",
   img: "100002.jpg",
   time: 1397736624(timestamp),
   likes:[1000002,1000006] (userID's),
   shares:[1000003,1000005] (userID's)
}

现在我想检索所有帖子还要计算每个帖子的喜欢和分享数量。我无法检索每个帖子的所有喜欢和分享,因为它浪费了空间。所以我选择mapReduce来计算喜欢和分享的数量。我的mapReduce操作是:

下面的代码是在php:

$map=function(){ emit(this.date,{postID:this.postID,userID:this.userID,title:this.title,postimg:this.postimg,text:this.text,date:this.date,like:this.like,share:this.share,like_count:this.like.length,share_count:this.share.length})}

$reduce=function(){ }

$result=$this->db->command(array(
            'mapreduce'=>"post"
            'map'=>$map,
            'reduce'=>$reduce,
            'out'=>array('inline'=>1),
                    'sort'=>array('date'=>-1)  

        ));

结果未排序。我知道sort选项是在mapReduce之前对文档进行排序。如何对结果进行排序?

有人帮助获得排序结果。

1 个答案:

答案 0 :(得分:0)

基本上你的查询可以使用.aggregate()来完成,这是一个比mapReduce更好的选择,因为它使用本机代码而不是JavaScript解释器,因此速度更快。

2.6及更高版本中的超级简单:

db.collection.aggregate([
    { "$project": {
        "postID":1,
        "userID": 1,
        "title": "1,
        "text": 1,
        "img": 1,
        "time": 1,
        "likes": { "$size": "$likes" },
        "shares": { "$size": "$shares" },
    }},
    { "$sort": { "time": -1 } }
])

更多涉及先前的2.4版本,仍然比mapReduce更快:

db.collection.aggregate([
    { "$project": {
        "_id": {
            "postID": "$postID",
            "userID": "$userId",
            "title": "$title",
            "text": "$text",
            "img": "$img",
            "time": "$time",
            "likes": "$likes",
            "shares": "$shares"
        },
        "likes": 1
    }},
    { "$unwind": "$likes" },
    { "$group": {
        "_id": "$_id",
        "likes": { "$sum": 1 }
        "shares": { "$first": "$_id.shares" }
    }},
    { "$unwind": "$shares" },
    { "$group": {
        "_id": "$_id",
        "likes": { "$first": "$likes" },
        "shares": { "$sum": 1 }
    }},
    { "$project": {
        "_id": 0,
        "postID": "$_id.postID",
        "userID": "$_id.userId",
        "title": "$_id.title",
        "text": "$_id.text",
        "img": "$_id.img",
        "time": "$_id.time",
        "likes": "$likes",
        "shares": "$shares"
    }},
    { "$sort": { "time": -1 } }
])

同样对于mapReduce,你会讨厌这是多么简单:

var mapper = function() { 

    emit(
        {   
            counter: counter,
            time: this.time
        },
        {
            postID: this.postID,
            userID:this.userID,
            title:this.title,
            postimg:this.postimg,
            text:this.text,
            time:this.time,
            like:this.like,
            share:this.share,
            like_count:this.like.length,
            share_count:this.share.length
        }
    );
    counter++;
};

然后调用:

db.collection.mapReduce(
    mapper,
    function(){},
    {
        "out":   { "inline": 1 },
        "sort":  { "time": -1 },
        "scope": { "counter": 0 }
    }
)

因此,通过使“输入”排序顺序为您想要的顺序,然后通过从映射器函数中的“范围全局”中指定“计数器”的“升序”顺序作为键的前导部分,“下降“秩序被保留。

但是使用聚合方法,它会更好地满足您的需求。