2012-03-30 91 views
4

尝试此solution后又进一步了,我还有一个关于mongodb的问题。按地图排序/按内联结果排序

我的问题是:

我如何可以排序的输出:

doc = {_id : 16, days : { 1 : 123, 2 : 129, 3 : 140, 4 : 56, 5 : 57, 6 : 69, 7 : 80 }}; 
db.so.insert(doc); 

map = function() { 
    emit(this._id, this.days["1"]); 
    emit(this._id, this.days["3"]); 
    emit(this._id, this.days["7"]); 
} 

reduce = function (k, vals) { 
    var sum = 0; 
    vals.forEach(function (v) {sum += v;}); 
    return sum; 
} 

res = db.so.mapReduce(map, reduce, {out : {inline : 1}}); 
res.find(); 

输出是这样的:

"results" : [ 
    { 
      "_id" : 16, 
      "value" : 225 
    }, 
    { 
      "_id" : 33, 
      "value" : 230 
    }, 
    { 
      "_id" : 302, 
      "value" : 274 
    } 

]

现在我想排序结果如下:

res.find().sort({ "results.value":-1 }); 

导致这个错误:

Sat Mar 31 01:15:45 TypeError: res.find().sort({'results.value':-1}) is not a function (shell):1 

是否有人能帮助我吗?

回答

6

下面是一个使用MongoDB的2.2 Aggregation Framework同一查询的例子:

db.so.aggregate(
    { $project : { 
    '_id' : 1, 
    'value' : { $add : ["$days.1","$days.3","$days.7"] }, 
    }}, 
    { $sort: { 'value': -1 }} 
) 

..和输出:

{ 
    "result" : [ 
     { 
      "_id" : 302, 
      "value" : 274 
     }, 
     { 
      "_id" : 33, 
      "value" : 230 
     }, 
     { 
      "_id" : 16, 
      "value" : 225 
     } 
    ], 
    "ok" : 1 
} 
6

这不会以这种方式与inline结果一起工作。相反,请尝试写入集合,然后对该集合进行排序。

res = db.so.mapReduce(map, reduce, {out : "tmpResults"}); 
db.tmpResult.find().sort({value:-1}); 
+0

你认为这将有可能与新的mongo聚合框架? – MadeOfSport 2012-03-31 11:04:27

+0

是的,我相信你可以用聚合框架来做到这一点。看起来像'$ project'这个'_id'和'sum',然后使用'$ sort'。这应该很容易测试,因为2.1可以下载。 – 2012-04-01 06:29:18

+0

你说得对。这很好 – MadeOfSport 2012-04-01 10:59:25

5

你完全可以排序results属性:

res = db.so.mapReduce(map, reduce, {out : {inline : 1}}); 
res.results.sort(function (a, b) { 
    if (a.value == b.value) { 
     return 0; 
    } 
    return a.value < b.value ? -1 : 1; 
});