Я пытаюсь сделать то, что должно быть довольно простой операцией в моей среде mongoDB / Node. У каждого документа в коллекции, на которую я нацеливаюсь, есть поле "openBalance", которое является числовым значением. Все, что я хочу сделать, это найти totalOpenBalance
, сложив все вместе.
Пока что при просмотре документации MongoDB $ add и $ sum, похоже, используются для выполнения операций над отдельными документами в коллекции, а не над самой коллекцией.
Это заставляет меня задуматься, есть ли другой подход к этому? Я пробовал множество конструкций, но ни одна из них не работает. Вот моя функция полностью:
exports.getClientData = async function (req, res, next) {
let MongoClient = await require('../config/database')();
let db = MongoClient.connection.db;
let search, skip, pagesize, page, ioOnly = false, client;
let docs = [];
let records = 0;
if (_.isUndefined(req.params)) {
skip = parseInt(req.skip) || 0;
search = JSON.parse(req.search);
pagesize = parseInt(req.pagesize) || 0;
page = parseInt(req.page) || 0;
client = req.client || '';
ioOnly = true;
}
else {
skip = parseInt(req.query.skip) || 0;
search = req.body;
pagesize = parseInt(req.query.pagesize) || 0;
page = parseInt(req.query.page) || 0;
client = req.query.client || '';
}
search = {};
if (skip === 0) {
skip = page * pagesize;
}
if (client) {
let arrClient = [];
arrClient = client.split(",");
if (arrClient) {
// convert each ID to a mongo ID
let mongoArrClient = arrClient.map(client => new mongo.ObjectID(client));
if (mongoArrClient) {
search['client._id'] = { $in: mongoArrClient };
}
}
}
console.log(search);
let counter = 0;
let count = await db.collection('view_client_data').find(search).count();
let totalClients = await db.collection('view_client_data').find(search).count({ $sum: "client._id" });
console.log('totalClients', totalClients);
let totalOpenBalance = await db.collection('view_client_data').find(search).count({ $sum: { "$add" : "openBalance" } });
console.log('totalOpenBalance', totalOpenBalance);
db.collection('view_client_data').find(search).skip(skip).limit(pagesize).forEach(function (doc) {
counter ++; {
console.log(doc);
docs.push(doc);
}
}, function (err) {
if (err) {
if (!ioOnly) {
return next(err);
} else {
return res(err);
}
}
if (ioOnly) {
res({ sessionId: sessID, count: count, data: docs, totalClients: totalClients, totalOpenBalance: totalOpenBalance });
}
else {
res.send({ count: count, data: docs, totalClients: totalClients, totalOpenBalance: totalOpenBalance });
}
});
}
Как вы можете видеть в приведенном выше коде, я получаю общее количество клиентов с этим кодом:
let totalClients = await db.collection('view_client_data').find(search).count({ $sum: "client._id" });
console.log('totalClients', totalClients);
Это прекрасно работает, складывая экземпляры клиента и давая мне общее количество.
Опять же, чтобы быть кристально чистым, я сталкиваюсь с проблемой в суммировании числового значения для всех значений openBalance
. У каждого документа есть поле openBalance
. Все, что я хочу сделать, это сложить их и вывести их в переменную под названием totalOpenBalance
и передать это в ответе, который я отправляю, как я делаю для totalClients
. Я пробовал множество вариантов, в том числе:
let totalOpenBalance = await db.collection('view_client_data').find(search).count({ $sum: { "$add" : "openBalance" } });
console.log('totalOpenBalance', totalOpenBalance);
и это:
let totalOpenBalance = await db.collection('view_client_data').find(search).aggregate({ $sum: { "$add" : "openBalance" } });
console.log('totalOpenBalance', totalOpenBalance);
... но, как я уже сказал, никто не работает. Иногда я получаю ошибку циклической ссылки, иногда aggregate is not a function error
, а иногда и другие ошибки. Я ломал голову, пытаясь понять это - и я полагаю, что это не должно быть так сложно, как только я пойму необходимый синтаксис. Как я могу получить мои totalOpenBalance
здесь?
Кстати, целевые документы выглядят примерно так:
{
"_id": "3hu40890sf131d361f1ad908",
"client": {
"_id": "4ft9d366121j04563be0b01d6",
"name": {
"first": "John",
"last": "Smith"
}
},
"openBalance": 128,
"lastPurchaseDate": "2018-01-19T00:00:00.000Z"
},