how can I find out the sum of a field in mongodb - mongodb

I am really new to mongoDB. In the given data structure how can i sum the misscallcount field
{
"_id" : ObjectId("596c5f6905c36efd35000009"),
"misscallDetails" : [
{
"contactId" : "1573778945692669180",
"misscallCount" : NumberInt(1),
"promotedOn" : ISODate("2017-08-04T13:54:17.298+0000")
},
{
"contactId" : "1573778945692669180",
"misscallCount" : NumberInt(1),
"promotedOn" : ISODate("2017-08-04T13:56:17.243+0000")
}
],
"promoId" : ObjectId("596c5f4705c36efd35000003"),
}
From comments:
I tried from my side but its give total 0 ;
db.promoledger.aggregate( [
{ $group: { _id: null, total: { $sum: "$misscallDetails.misscallCount" } }}
])

You need to $unwind the array before grouping for sum
b.promoledger.aggregate( [
{$unwind: '$misscallDetails'},
{ $group: { _id: null, total: { $sum: "$misscallDetails.misscallCount" } }}
])

Related

Create new properties based on embedded array elements in MongoDB

I have this kind of document
{
"_id" : ObjectId("573342930348ce88ff1685f3"),
"presences" : [
{
"_id" : ObjectId("573342930348ce88ff1685f2"),
"createdAt" : NumberLong(1458751869000)
},
{
"_id" : ObjectId("573342930348ce88ff1685f5"),
"createdAt" : NumberLong(1458751885000)
},
{
"_id" : ObjectId("573342930348ce88ff1685f7"),
"createdAt" : NumberLong(1458751894000)
}
]
}
How can I extract first and last presences element to new properties firstPresence and lastPresence like this?
{
"_id" : ObjectId("573342930348ce88ff1685f3"),
"firstPresence": {
"_id" : ObjectId("573342930348ce88ff1685f2"),
"createdAt" : NumberLong(1458751869000)
},
"lastPresence": {
"_id" : ObjectId("573342930348ce88ff1685f7"),
"createdAt" : NumberLong(1458751894000)
},
"presences" : [
...
]
}
I want to use a query that can be applied to all documents in one time.
You need to $unwind your presences array to do the aggregation. Before grouping you can sort them by createdAt to utilize $first and $last operators.
db.collection.aggregate(
[
{ $unwind: "$presences" },
{ $sort: { "presences.createdAt": 1 } },
{
$group: {
_id: "$_id",
"presences": { $push: "$presences" },
"lastPresence": { $last: "$presences" },
"firstPresence": { $first: "$presences" },
}
},
{ $out : "collection" }
])
Last aggregation pipeline ($out) will replace existing collection.
According to above mentioned description as a solution to it please try executing following aggregate query into MongoDB shell
db.collection.aggregate(
// Pipeline
[
// Stage 1
{
$project: {
first: {
$arrayElemAt: ["$presences", 0]
},
last: {
$arrayElemAt: ["$presences", -1]
},
presences: 1
}
},
]
);

MongoDB nested group by query

I want to count correct, incorrect and unattempted question count. I am getting zero values.
Query -
db.studentreports.aggregate([
{ $match: { 'groupId': 314 } },
{ $unwind: '$questions' },
{ $group:
{
_id: {
dateTimeStamp: '$dateTimeStamp',
customerId: '$customerId'
},
questions : { $push: '$questions' },
unttempted : { $sum : { $eq: ['$questions.status',0]}},
correct : { $sum : { $eq: ['$questions.status',1]}},
incorrect : { $sum : { $eq: ['$questions.status',2]}},
Total: { $sum: 1 }
}
}
])
Schema structure -
{
"_id" : ObjectId("59fb46ed560e1a2fd5b6fbf4"),
"customerId" : 2863318,
"groupId" : 309,
"questions" : [
{
"questionId" : 567,
"status" : 0,
"_id" : ObjectId("59fb46ee560e1a2fd5b700a4"),
},
{
"questionId" : 711,
"status" : 0,
"_id" : ObjectId("59fb46ee560e1a2fd5b700a3")
},
....
values unttempted, correct and incorrect are getting wrong -
"unttempted" : 0,
"correct" : 0,
"incorrect" : 0,
"Total" : 7558.0
Group by is required based on datetime and customerId.
Can some one correct query ?
Thanks.
You want to sum these fields only if a certain condition is met.
You just have to rewrite your group statement like this:
{ $group:
{
_id: {
dateTimeStamp: '$dateTimeStamp',
customerId: '$customerId'
},
questions : { $push: '$questions' },
unttempted : { $sum : {$cond:[{ $eq: ['$questions.status',0]}, 1, 0]}},
correct : { $sum : {$cond:[{ $eq: ['$questions.status',1]}, 1, 0]}},
incorrect : { $sum : {$cond:[{ $eq: ['$questions.status',2]}, 1, 0]}},
Total: { $sum: 1 }
}
}
Check out the documentation $eq. $eq compares and returns true or false. So then your $sum cannot do anything with that result

MongoDB $group will not allow me to $project extra fields

I almost got this one working, but I simply cannot figure out why the $project part does not work for normal fields....
This is "invoice" table:
{
"_id" : "AS6D0",
"invoiceNumber" : 23,
"bookingId" : "AS6D0",
"createDate" : 1490369414,
"dueDate" : 1490369414,
"invoiceLines" : [
{
"lineText" : "Rent Price",
"amountPcs" : "8 x 7500",
"amountTotal" : 60000
},
{
"lineText" : "Discount(TIKO10)",
"amountPcs" : "10%",
"amountTotal" : -10000
},
{
"lineText" : "Final cleaning",
"amountPcs" : "1 x 5000",
"amountTotal" : 5000
},
{
"lineText" : "Reservation fee paid already",
"amountPcs" : "1 x -20000",
"amountTotal" : -20000
}
],
"managerId" : "4M4KE"
}
And this is my query
db.getCollection('invoice').aggregate([
{
$match: {
bookingId: "AS6D0"
}
},
{
$unwind: "$invoiceLines"
},
{
$group: {
_id: "$_id",
sum: {$sum: "$invoiceLines.amountTotal"}
}
},
{
$project:{
"_id" : 0,
"invoiceNumber" : 1,
"dueDate" : 1,
"sum" : 1
}
}
])
I get the _id and the sum, but it wont show invoiceNumber and dueDate
You could use a trick like this :
db.getCollection('invoice').aggregate([
{ $match: { } },
{ $unwind: "$invoiceLines" },
{ $group: { _id: "$_id",
sum: {$sum: "$invoiceLines.amountTotal"},
invoiceNumber: { $addToSet: "$invoiceNumber" },
dueDate: { $addToSet: "$dueDate" } } }
]);
Thanks to Mateo, this is what I ended up with:
(I do the unwind on the fields to avoid single value arrays)
Update : You don't have to $addToSet to reduce the fields into single value arrays and $unwind. Use $first instead.
db.getCollection('invoice').aggregate([
{
$match: {
bookingId: "AS6D0"
}
},
{
$unwind: "$invoiceLines"
},
{
$group: {
_id: "$_id",
sum: {$sum: "$invoiceLines.amountTotal"},
invoiceNumber: { $first: "$invoiceNumber" },
dueDate: { $first: "$dueDate" }
}
},
{
$project:{
"_id" : 0,
"invoiceNumber" : 1,
"dueDate" : 1,
"sum" : 1
}
}
])

Can not get $sum in aggregate function in MongoDB

Here's my data format :
"request" : {
"_id" : 1003,
"user" : {
"username" : "",
"password" : "",
"_id" : 1111,
"gender" : "male",
},
"request" : {
"merchantid" : "TA456",
"txnAmount" : 18000,
"fee" :0,
"IssuerID" : "18801111",
"bankID" : "888888",
}
},
"confirmation" : true
}`
I can not get the sum of 'request.request.txnAmount' group by 'request.user._id'.
Here's my query:
db.getCollection('megabank_response').aggregate(
[ { $group : {
_id : "request.user._id",
totalPrice: { $sum: "request.request.txnAmount"},
count: { $sum: 1 }
}
}
])
And get the result :
{
"_id" : "request.user._id",
"total Price" : 0,
"count" : 4.0
}
Can anyone help me why my query cannot calculate the sum?
You seem to missing the $ symbol in the group aggregation function.
db.megabank_response.aggregate([{
$group: {
_id: "request.user._id",
ss: {
$sum: "request.request.txnAmount"
}
}
}]);
gives: { "_id" : "request.user._id", "ss" : 0 }
But the correct answer is:
db.megabank_response.aggregate([{
$group: {
_id: "$request.user._id",
ss: {
$sum: "$request.request.txnAmount"
}
}
}]);
I've managed to figured out the query using answer from this source.
However, my query is stil a little bit too messy. Any ways to optimize it?
db.getCollection('megabank_response').aggregate([
{
"$match": {
"request.user._id": 1111
}
},
{
"$group":{
_id : "request.user._id",
totalPrice: { $sum: '$request.request.txnAmount'},
count: { $sum: 1 }
}
}
])
Result:
{
"_id" : "request.user._id",
"totalPrice" : 62000,
"count" : 3.0
}
Try:
db.getCollection('megabank_response').aggregate([{
$group: {
_id : "request.user._id",
totalPrice: { $sum: "$request.request.txnAmount"},
count: { $sum: 1 }
}
}])
You can also use totalPrice: { $sum: "$txnAmount"} to display the sum of your transaction amount. I was working on the GET request of Total Sales in the e-shop that I developed, and I had faced the same issue. Just for your reference, here is my code:
//GET total sales data for the ADMIN
router.get('/get/totalsales', async(req, res) => {
const totalSales = await Order.aggregate([
{ $group: { _id: null, totalSales : { $sum: '$totalPrice' }}} // Use $totalPrice instead of totalPrice
])
if(!totalSales) {
return res.status(400).send('The sales cannot be generated')
}
res.send({totalSales: totalSales})
})
Hope this helps :)

Get record of another field with aggregate

I am new in MongoDB world.
I've following data in my collection
{
"_id" : ObjectId("5735d8d4d147aa34e440988f"),
"DeviceLogId" : "26962",
"DeviceId" : "10",
"UserId" : "78",
"LogDateTime" : ISODate("2016-05-12T07:52:44.000+0000")
}
{
"_id" : ObjectId("5735d8d4d147aa34e4409890"),
"DeviceLogId" : "26963",
"DeviceId" : "10",
"UserId" : "342",
"LogDateTime" : ISODate("2016-05-12T07:54:09.000+0000")
}
{
"_id" : ObjectId("5735d8d4d147aa34e4409891"),
"DeviceLogId" : "26964",
"DeviceId" : "10",
"UserId" : "342",
"LogDateTime" : ISODate("2016-05-12T07:54:10.000+0000")
}
{
"_id" : ObjectId("5735d8d4d147aa34e4409892"),
"DeviceLogId" : "26965",
"DeviceId" : "10",
"UserId" : "78",
"LogDateTime" : ISODate("2016-05-12T07:54:27.000+0000")
}
I want to query DeviceId of each user with maximum LogDateTime using group by.
I've written group by query like below but have no idea how would I get DeviceLogId for each record.
collectionName.aggregate(
[{
$match: { LogDateTime: { $gt: todaysDateStart, $lt: todayDateEnd } }
}, {
$group: {
_id: "$UserId",
maxPunchTime: { $max: { $add: [ "$LogDateTime", 330*60000 ] } },
}
}])
In MSSQL, I could easily do it with nested query but I've no idea how would I achieve that in MongoDB.
Thanks in advance.
Use the $addToSet Group Accumulator:
collectionName.aggregate(
[{
$match: { LogDateTime: { $gt: todaysDateStart, $lt: todayDateEnd } }
}
, {
$group: {
_id: "$UserId",
maxPunchTime: { $max: { $add: [ "$LogDateTime", 330*60000 ] } },
deviceLogIds:{$addToSet: "$DeviceLogId"} //<----
}
} ,
{ $sort: {"maxPunchTime" : -1} } , {$limit : 1} //Sort Descending + Limit to 1
])
Add deviceid to an array in group phase,
Device:{$addToSet:deviceId}