2015-09-08 2 views
0

У меня есть большой набор данных, подобный ниже в MongoDBMongoDB Aggregation - СУММЫ ГДЕ

Я хочу, чтобы запустить агрегацию в MongoDB, который был бы эквивалентом этого SQL:

SELECT SUM(cores) from machines 
WHERE idc='AMS' AND cluster='1' AND type='Physical'; 

Как я иду о переходе в MongoDB?

[ 
    { 
     "_id" : "55d5dc40281077b6d8af1bfa", 
     "hostname" : "x", 
     "domain" : "domain", 
     "description" : "VMWare ESXi 5", 
     "cluster" : "1", 
     "type" : "Physical", 
     "os" : "EXSi", 
     "idc" : "AMS", 
     "environment" : "DR", 
     "deviceclass" : "host", 
     "cores" : "64", 
     "memory" : "256", 
     "mounts" : [ ], 
     "roles" : [ 
       "ESX-HOST" 
     ], 
     "ipset" : { 
       "backnet" : "1" 
     }, 
     "frontnet" : [ ], 
     "created" : "2015-09-08T07:35:03.343Z" 
    }, 
    { 
     "_id" : "55d5dc40281077b6d8af1bfb", 
     "hostname" : "x", 
     "domain" : "domain", 
     "description" : "VMWare ESXi 5", 
     "cluster" : "1", 
     "type" : "Physical", 
     "os" : "EXSi", 
     "idc" : "AMS", 
     "environment" : "DR", 
     "deviceclass" : "host", 
     "cores" : "64", 
     "memory" : "256", 
     "mounts" : [ ], 
     "roles" : [ 
       "ESX-HOST" 
     ], 
     "ipset" : { 
       "backnet" : "1" 
     }, 
     "frontnet" : [ ], 
     "created" : "2015-09-08T07:35:03.346Z" 
    } 
] 
+1

Существует страница в руководстве со всех общих операций в качестве примеров: [SQL агрегации Mapping Диаграмма] (http://docs.mongodb.org/v3 0,0/ссылка/SQL-агрегация сравнение /). Я предлагаю вам прочитать его. –

+2

Для этого вам не нужна агрегация. Я думаю, что использование хочет ['.count'] (http://docs.mongodb.org/manual/reference/method/db.collection.count/), потому что SUM (_id) здесь не имеет смысла. – styvane

+0

извините - опечатка - теперь должно быть больше смысла – Corbin

ответ

4

Сначала вам нужно обновить свои документы, потому что значения cores - это строка вместо номера. Для этого мы используем операции "Bulk".

var bulk = db.machines.initializeOrderedBulkOp(), 
    count = 0; 
db.machines.find({ "cores": { "$type": 2 }}).forEach(function(doc){ 
    var cores = parseInt(doc.cores); 
    bulk.find({ "_id": doc._id }).update({  
     "$set": { "cores": cores } }) 
     count++; 
     if (count % 200 == 0){ 
      // execute per 200 operations and re-init 
      bulk.execute();  
      bulk = db.machines.initializeOrderedBulkOp(); 
     } 
    }) 

// clean up queues 
if (count % 200 != 0) 
    bulk.execute(); 

Затем с помощью платформы агрегации мы можем получить сумму cores. Сначала нам нужно отфильтровать наши документы с помощью оператора $match, а на этапе $group мы используем оператор $sum, чтобы получить сумму значений cores.

db.machines.aggregate([ 
    { "$match": { "idc": "AMS", "cluster": "1", "type": "Physical" }}, 
    { "$group": { "_id": null, "sum_cores": { "$sum": "$cores" }}} 
]) 

Который возвращает:

{ "_id" : null, "sum_cores" : 128 } 
0

Хотя я не выполнил его, чтобы проверить его проверить это:

db.<collection>.aggregation([ 
{$match: { 
     idc: 'AMS', 
     cluster: 1, 
     type:'Physical' 
    } 
}, 
{$group: { 
      _id: null, 
      sum: {$sum: "$_id"} 
    } 
}, 
{$project: { 
     _id:0, 
     sum:1 
    } 
} 

])

0

Я думаю, что с помощью рамки агрегирование невозможно, так как 'cores' сохраняется как string, и в настоящее время mongo не позволяет проецировать строку как число в фазе трубопровода $project. Тот же результат с помощью простой JavaScript:

var tmp = db.cores.find({idc: 'AMS', cluster: '1', type: 'Physical'}, {_id: 0, cores: 1}) 
var totalCores = 0; 
tmp.forEach(function(doc) { 
    totalCores += parseInt(doc.cores); 
}) 

print(totalCores) 

, если я понимаю проблему правильно.