Как я могу перевести следующий запрос Sql
для Mongo
?
select a,b,sum(c) csum from coll where active=1 group by a,b order by a
Есть ли способ выполнить группу и отсортировать запрос с Mongo?
Как я могу перевести следующий запрос Sql
для Mongo
?
select a,b,sum(c) csum from coll where active=1 group by a,b order by a
Есть ли способ выполнить группу и отсортировать запрос с Mongo?
Вдохновленный этим примером на веб-сайте mongo.
ОБЩИЕ ДАННЫЕ:
> db.stack.insert({a:1,b:1,c:1,active:1})
> db.stack.insert({a:1,b:1,c:2,active:0})
> db.stack.insert({a:1,b:2,c:3,active:1})
> db.stack.insert({a:1,b:2,c:2,active:0})
> db.stack.insert({a:2,b:1,c:3,active:1})
> db.stack.insert({a:2,b:1,c:10,active:1})
> db.stack.insert({a:2,b:2,c:10,active:0})
> db.stack.insert({a:2,b:2,c:5,active:1})
MONGO QUERY:
> db.stack.aggregate(
... {$match:{active:1}},
... {$group:{_id:{a:"$a", b:"$b"}, csum:{$sum:"$c"}}},
... {$sort:{"_id.a":1}})
РЕЗУЛЬТАТ:
{"result" : [
{"_id" : {"a" : 1,"b" : 2},"csum" : 3},
{"_id" : {"a" : 1,"b" : 1},"csum" : 1},
{"_id" : {"a" : 2,"b" : 2},"csum" : 5},
{"_id" : {"a" : 2,"b" : 1},"csum" : 13}
],"ok" : 1}
(ПРИМЕЧАНИЕ: я немного переформатировал результат оболочки, чтобы он был более читабельным)
Используя агрегатную среду, вы можете сделать следующее:
db.coll.aggregate({
$group: {
_id: "$a",
countA: { $sum: 1},
sumC:{ $sum: "$c"},
},
$sort:{a:1}
});
Однако, если у вас слишком много данных, вы можете получить следующее сообщение об ошибке:
{
"errmsg" : "exception: aggregation result exceeds maximum document size (16MB)",
"code" : 16389,
"ok" : 0
}
Узнайте больше о переводе с SQL на монго здесь: http://docs.mongodb.org/manual/reference/sql-aggregation-comparison/
Я создал гистограмму, и то, что я сделал с версией 2.2.2, было:
answer = db.coll.group(...)
db.histo.insert(answer)
db.histo.find().sort({ field: 1 })
В этот момент, если вам это не нужно, просто db.histo.drop()
.
Вы также можете избежать этой переменной:
db.histo.insert(db.coll.group(...))
db.histo.ensureIndex({ field: 1 })
API агрегирования mongodb, похоже, изменился. Теперь вы бы сделали
db.coll.aggregate([
{
$group: {
_id: "$a",
countA: { $sum: 1},
sumC:{ $sum: "$c"},
}
},
{
$sort:{a:1}
}
])
Обратите внимание на синтаксис массива для аргумента для aggregate(). Вы также добавляете в ссылку элементы $match, $limit и т.д. В качестве элементов этого массива.
См
http://www.mongodb.org/display/DOCS/Aggregation http://www.mongodb.org/display/DOCS/SQL+to+Mongo+Mapping+Chart
или объединить его, используя map-reduce.
db.coll.group(
{key: { a:true, b:true },
cond: { active:1 },
reduce: function(obj,prev) { prev.csum += obj.c; },
initial: { csum: 0 }
});
Вы можете выполнить его в MongoDB
Пока Агрегационная структура является выпуском в MongoDB 2.1, вызов для группы, как в this answer, является довольно медленным, поскольку он использует часть JavaScript в базе данных JavaScript.
Вы можете использовать более быстрый подход для подсчета групп:
var res = [];
for( var cur_a = db.coll.distinct('a'); cur_a.hasNext(); ) {
var a = cur_a.next();
for( var cur_b = db.coll.distinct('b'); cur_b.hasNext(); ) {
var b = cur_b.next();
res.push({ 'a': a, 'b' : b 'count': db.coll.count({'a':a,'b':b})}
}
}
Это будет быстрее, если у вас есть индексы на a и b
db.coll.ensureIndex({'a':1,'b':1})
В дополнение к предыдущим ответам, если вы хотите отсортировать по сумме (результату совокупности), а не по фактическому столбцу, вы можете сделать это:
db.your_collection.aggregate([
{
$group: {_id: "$your_document_name", count: {$sum: 1}}
},
{
$sort: {"count":-1}
}
])
Это будет эквивалентно следующему стандартному синтаксису SQL-кода:
select col_a, count(col_a) as b
from table
group by col_a
order by b desc
Я хочу добавить следующий запрос, в качестве примера, он может быть полезен в случае двух группировок.
Запрос:
db.getCollection('orders').aggregate([
{$match:{
tipo: {$regex:"[A-Z]+"}
}
},
{$group:
{
_id:{
codigo:"1",
fechaAlta:{$substr:["$fechaAlta",0,10]},
},
total:{$sum:1}
}
},
{$sort:
{"_id":1}
},
{$group:
{
_id:"$_id.codigo",
fechasAltas:
{
$push:
{
fechaAlta:"$_id.fechaAlta",
total:"$total"
}
},
totalGeneral:{$sum:"$total"}
}
}
]);
Отклик:
{
"_id" : "1",
"fechasAltas" : [
{
"fechaAlta" : "1940-01-01",
"total" : 13.0
},
{
"fechaAlta" : "2007-05-14",
"total" : 115.0
},
{
"fechaAlta" : "2008-09-30",
"total" : 58.0
},
.
.
.
],
"totalGeneral" : 50620.0
}