Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoose sum a value across all documents

I am looking to count all columns with the name amount in the documents that match my query,

 tickets.count({time: {$gte: a}, time: {$lte: tomorrow}}).then(function (numTickets) {

How can I get the total result of the document column called amount?

Example, if I do have:

{ time: 20, amount: 40}
{ time: 40, amount: 20}

it would return the total amount(60)?

Remember that I do need to use {time: {$gte: a}, time: {$lte: tomorrow} in the query.

How would I do this?

like image 423
maria Avatar asked Sep 20 '16 07:09

maria


People also ask

How do you sum the value of a key across all documents in a MongoDB collection?

To get sum the value of a key across all documents in a MongoDB collection, you can use aggregate().

How do I sum fields in MongoDB?

If used on a field that contains both numeric and non-numeric values, $sum ignores the non-numeric values and returns the sum of the numeric values. If used on a field that does not exist in any document in the collection, $sum returns 0 for that field. If all operands are non-numeric, $sum returns 0 .

What does aggregate do in mongoose?

Mongoose's aggregate() function returns an instance of Mongoose's Aggregate class. Aggregate instances are thenable, so you can use them with await and promise chaining. The Aggregate class also supports a chaining interface for building aggregation pipelines.

What is $project in MongoDB?

The $project takes a document that can specify the inclusion of fields, the suppression of the _id field, the addition of new fields, and the resetting of the values of existing fields. Alternatively, you may specify the exclusion of fields. Specifies the inclusion of a field.


1 Answers

Try it with the aggregation framework using the $match and $group operators, i.e. something like this

db.tickets.aggregate([
    { $match: { time: {$gte: a, $lte: tomorrow} } },
    { $group: { _id: null, amount: { $sum: "$amount" } } }
])

for example with test data like this

/* 1 */
{
    "_id" : ObjectId("57e0ed40828913a99c2ceb46"),
    "time" : 20,
    "amount" : 40
}

/* 2 */
{
    "_id" : ObjectId("57e0ed40828913a99c2ceb47"),
    "time" : 40,
    "amount" : 20
}

/* 3 */
{
    "_id" : ObjectId("57e0ed40828913a99c2ceb48"),
    "time" : 50,
    "amount" : 10
}

/* 4 */
{
    "_id" : ObjectId("57e0ed40828913a99c2ceb49"),
    "time" : 10,
    "amount" : 5
}

a pipeline (with dummy time range) like the following

db.tickets.aggregate([
    { $match: { time: {$gte: 20, $lte: 40} } },
    { $group: { _id: null, amount: { $sum: "$amount" } } }
])

would give you a result like this

/* 1 */
{
    "_id" : null,
    "amount" : 60
}

Pipeline in action

like image 78
DAXaholic Avatar answered Sep 22 '22 11:09

DAXaholic