有没有办法在mongodb中同时按两个字段排序? 所以我们假设我们在集合中有以下文档:
{ id: 'name1', last_1: 5, last_2: 2 },
{ id: 'name2', last_1: 1, last_2: 9 },
{ id: 'name3', last_1: 4, last_2: 3 }
我希望它按降序排序,检查last_1和last_2,结果将是: document2(last_2中的9),document1(last_1中的5),document3(last_1中的4)。我还需要知道它在结果中的哪个字段。 我目前的聚合看起来像这样:
{ $group:
{ _id: { id: '$name' },
last_1: { $last: '$field1' },
last_2: { $last: '$field2' },
}
},
{ $sort : { /* don't know what to put in here */ } },
{ $limit: some_limit }
UPD:我可能必须完全删除排序/限制并使用一些自定义节点功能,因为看起来我只能使用mongo来实现它,特别是因为额外的要求是列出如果两个字段的字段都大于其他文档,则同一文档两次。
答案 0 :(得分:3)
也许是这样的,
db.test.aggregate([
{$project: {name: 1, field1: 1, field2: 1}},
{$group: {_id: '$name', field_1: { $last: '$field1' }, field_2: { $last: '$field2' }}},
{$project: {name: 1, field_1: 1, field_2: 1, cmp: { $cmp: ['$field_2', '$field_1'] } }},
{$sort: { cmp: -1, field_1: -1, field_2: -1 }}
])
db.test.aggregate([
{$project: {name: 1, field1: 1, field2: 1}},
{$group: {_id: '$name', field_1: { $last: '$field1' }, field_2: { $last: '$field2' }}},
{$project: {
name: 1,
field_1: 1,
field_2: 1,
largest: { $cond: [ {$gt: ['$field_2', '$field_1']}, '$field_2', '$field_1'] }
}},
{$sort: { largest: -1 }}
])
答案 1 :(得分:1)
您要求sort
根据字段last_1
和last_2
对last_1
您的文档进行汇总,其中最大的字段可以汇总如下:
last_2
和sort
中较大的值
descending
。project
db.collection.aggregate([
{$project:{"id":"$id",
"last_1":1,
"last_2":1,
"sortField":{$cond:[
{$gt:["$last_1","$last_2"]},
"$last_1",
"$last_2"]}}},
{$sort:{"sortField":-1}},
{$project:{"_id":0,
"id":"$id",
"last_1":1,
"last_2":1}}
])
订单中的记录。汇总代码:
{{1}}
答案 2 :(得分:0)
好吧,这就是它结束的原因,我担心与mongodb-native相比它会变得太慢,但实际上并没有那么糟糕:
Test.aggregate(
[
{ $match:
{'modified': { $gte: settings.period } }
},
{ $group:
{ _id: { name: '$name' },
last_1: { $last: '$field_1' },
last_2: { $last: '$field_2' },
}
}
],
function (err, result) {
if (err) callback(err);
else {
var arr = [];
for (var i = 0; i < result.length; i++) {
var obj = result[i];
arr.push({ id: obj._id, sort: obj.last_1 });
arr.push({ id: obj._id, sort: obj.last_2 });
}
arr.sort(compare).reverse();
arr = arr.slice(0, settings.limit);
var arr2 = [];
for (i = 0; i < arr.length; i++) {
var id = arr[i].id;
var element = result.filter(function(element) {
return element._id == id;
});
arr2.push(element[0]);
}
callback(null, arr2);
}
});
);
function compare(a, b) {
if (a.sort < b.sort)
return -1;
if (a.sort > b.sort)
return 1;
return 0;
}