mongoDB, sum many values query - mongodb

I have a list of items, and I want mongoDB return the result of the sum of their price.
Schema = {
_id: ObjectId,
price: Integer,
}
I'm trying using the aggregation framework, but I can't figure out how correctly use it.
Here an example
db.items.aggregate([
{$match: {_id: {$in: [103070,103069]}}},
{$unwind: "$items"},
{$group: {_id: "$items", count: {$sum: "$items.price"}}},
{$project: {_id: 1}}
])

you are not correctly using the $in operator... $in is used to find elements inside an array, in this case you should use $gte (greater than equal), $lte (less then equal)... Your schema simply don't have "nodeId"... $unwind is used when you have an array inside the document what I presume is not the case... If i understand the query should be something like:
db.items.aggregate([
{$match : {_id : { $gte : 103069, $lte : 103070 } } },
{$group: {_id: null, count: {$sum: "$price"}}},
{$project: {_id: 0, count : 1}}
])

Related

how to getting the count with all records

I am trying this mongodb aggregation. I got the output but how can I get the count value with all records.
db.STREETLIGHTS.aggregate(
[
{$match : {"CreateDate":{$gt:new Date(ISODate("2018-04-09T23:54:16.064Z") - 24*60*60 * 1000)}}},
{ $project: {_id:1, SLC_ID:1,LONGITUDE:1,LATITUDE:1,DCUID:1,CUMILITIVE_KWH:1,LAMPSTATUS:1,CreateDate:1 } },
]
)
Please try this.
db.STREETLIGHTS.aggregate([
{$match : {"CreateDate":{$gt:new Date(ISODate("2018-04-09T23:54:16.064Z") - 24*60*60 * 1000)}}},
{$project: {_id:1, SLC_ID:1,LONGITUDE:1,LATITUDE:1,DCUID:1,CUMILITIVE_KWH:1,LAMPSTATUS:1,CreateDate:1 } },
{$group: {_id: null, count: {$sum: 1}}}
])
You need to use the $sum operator in the $project stage :
{$project: {
// Your others projections
total: {$sum: 1}
}

Count occurence of string in an array of string in all document in mongodb

All my document in my database (data) have a tags_data :
tags_data : [ "am", "gi", "bab", "as", "bru", "dan", "tea", "wec", "fuy" ]
So i would like to sort a recap of all tags with the number of occurence for each tag and if possible sort them in an descending sort
I'am trying to do it like this :
db.data.aggregate(
{$unwind: '$tags_data'},
{$group: {_id: '$tags_data', sum: {$sum: +1}}}
);
Thanks and regards
The answer was :
db.data.aggregate(
{$unwind: '$tags_data'},
{$group: {_id: '$tags_data', sum: {$sum: +1}} },
{$sort: {sum: -1}}
);
thanks

How do you return multiple results from a mongoDB aggregate() query?

Here is a query which runs a match, and then returns the number of unique entries in a specific field:
db.sequences.aggregate([{$match: {id: 5}}, {$group : {_id : "$field"} }, {$group: {_id:1, count: {$sum : 1 }}}])
However, what if I wanted to return multiple values, such as a count of all of the documents in the original match aggregation, the first 50 documents in the original match, and the number of unique entries of a field2 for the same matched set of documents?
Would I be able to write 1 aggregate query that returns all of these values?
You need to do two separate $group stages. First $group by the filed field, and then $push the resulting documents into an array and at the same time accumulate count from each document, to obtain the total sum.
db.sequences.aggregate(
[
{$match: {id: 5}},
{$group :
{
_id : "$field",
count: {$sum: 1}
}
},
{$group :
{
_id : null,
totalNumberOfMatches: {$sum: '$count'},
totalNumberOfUniqueMatches: {$sum: 1},
uniqueMatchesField:
{
$push:
{
field: '$_id',
count: '$count'
}
}
}
},
]
)

MongoDB Aggregation Framework $Project additional ObjectId reference field

Say I have the following:
this.aggregate(
{$unwind: "$tags"},
{$match: {tags: {$in: pip.activity.tags}}},
{$group : {_id : '$_id',matches:{$sum:1}}},
{$project: { _id: 0,matches:1}},
{$sort: {matches:-1 }},
callback
);
how would I go about including an additional 'external' objectId field in the results? e.g if I have the following:
var otherField = new ObjectId('xxxxxxx');
this.aggregate(
{$unwind: "$tags"},
{$match: {tags: {$in: pip.activity.tags}}},
{$group : {_id : '$_id',matches:{$sum:1}}},
{$project: { _id: 0,matches:1,otherField:otherField}}, <-- include otherField
{$sort: {matches:-1 }},
callback
);
Is this possible or should I be using a forLoop or MapReduce for this particular step? I'm looking for something really efficient.
The $project pipeline operator would not let you inject the object, but you can probably insert the object id earlier in the $group operator. If you have a collection:
db.foo.save({_id:1,tags:['a','b']})
db.foo.save({_id:2,tags:['b','c']})
db.foo.save({_id:3,tags:['c','d']})
You can then write:
db.foo.aggregate({
$unwind: "$tags"},{
$match: { tags: {$in: ['b','c'] } }},{
$group: { _id: "$_id", matches: {$sum: 1 }, otherField: {$min: new ObjectId()} }},{
$project: { _id: 0, matches: 1, otherField: 1 }},{
$sort: { matches: -1 }})
The $min or $max can be used here, but it expects an operator or reference to a field so you have to give it one..

Trying to extract the $first document from collection

After piping various documents through the aggregate framework I finally have the resultant documents.
The problem now is that I only want the $first and $last document.
The final document looks like this (huge list):
...
{
"_id" : "Kaila Deibler",
"count" : 406
},
{
"_id" : "Jessika Dagenais",
"count" : 406
},
{
"_id" : "Tamika Schildgen",
"count" : 404
},
...
The mongo shell command that I used to produce the document is:
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}}}, {$sort: {count: -1}}])
But I only need the first and last document so I attempted something like this:
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}}}, {$sort: {count: -1}}, {$first: "$_id"}])
I tried other implementations but can't seem to figure out when/where to implement $first and $last
Any suggestions?
$first and $last are aggregation functions in the $group pipeline, which means you need to use them inside the $group document.
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}, first: {$first:"$_id"}}}, {$sort: {count: -1}}])
Similarly for $last
You can find an example that shows this here
Here is my own answer to this question:
db.talks.aggregate([{$project: {_id: 0, comments: "$comments"}}, {$unwind: "$comments"}, {$group: {_id: "$comments.author", count: {$sum: 1}}}, {$sort: {count: -1}}, {$group: {_id: "$_id.comments.author", first: {$first: "$_id"}, last: {$last: "_id"}}}])
Since I want to pull the first and last document after the sort I have to apply another $group with $first and $last. The result:
{
"result" : [
{
"_id" : null,
"first" : "Elizabet Kleine",
"last" : "Mariela Sherer"
}
],
"ok" : 1
}
Note the "_id" : null. Is this necessary?
If anyone has a better solution please share.