I have a dataset like t
{
"_id" : ObjectId("5a867bae000e4f1c9c77d36d"),
"userid" : "5a20ee1acdacc7086ce7742d",
"sprice" : null,
"lprice" : 4.2,
"fruit" : "#Apple",
"createdate" : ISODate("2018-02-16T06:35:26.285Z"),
"__v" : 0
},
{
"_id" : ObjectId("5a867bae000e4f1c9c77d36e"),
"userid" : "5a20ee1acdacc7086ce7742e",
"sprice" : 3.5,
"lprice" : null,
"fruit" : "#Apple",
"createdate" : ISODate("2018-02-16T06:35:26.285Z"),
"__v" : 0
},
{
"_id" : ObjectId("5a867bae000e4f1c9c77d36e"),
"userid" : "5a20ee1acdacc7086ce7742e",
"sprice" : 8.6,
"lprice" : 2.2,
"fruit" : "#Apple",
"createdate" : ISODate("2018-02-16T06:35:26.285Z"),
"__v" : 0
}
for this I have to calculate the Average sprice of '#Apple' and neglect those entry which have value NULL.
For this My query is like this which returns exactly what I want, i.e
db.Collection.aggregate([
{ "$match": {
"fruit": "#Apple",
"sprice": {$ne:null}
}},
{ "$group": {
"_id": null,
"sprice": { "$avg": "$sprice" }
}}
])
It gives me the result. Now my Question is If I want to get the Individual Result of sprice and lprice then How My query is modified.
Expected answer will be like this:
{ "_id" : null, "sprice" : 6.05 } // Already Get from this query
{ "_id" : null, "lprice" : 3.2 } //Desired Result.
Any Help is Appreciated
With $facet
db.Collection.aggregate([
{ "$match": { "fruit": "#Apple" } },
{
"$facet": {
"sprice": [
{ "$match": { "sprice": { "$ne": null } } },
{ "$group": {
"_id": null,
"sprice": { "$avg": "$sprice" }
}}
],
"lprice": [
{ "$match": { "lprice": { "$ne": null } } },
{ "$group": {
"_id": null,
"lprice": { "$avg": "$lprice" }
}}
]
}
}
])
Sample Output
[
{ "sprice": { "_id" : null, "sprice" : 6.05 } },
{ "lprice": { "_id" : null, "lprice" : 3.2 } }
]
$avg ignores non numeric values by default so no explicit null filter is required, below pipeline will give you the desired results
db.Collection.aggregate([
{ "$match": {
"fruit": "#Apple"
}},
{ "$group": {
"_id": null,
"sprice": { "$avg": "$sprice" },
"lprice": { "$avg": "$lprice" }
}}
])
Related
I want to group by and count follow_user.tags.tag_id per record, so no matter how many times the same tag_id show up on the same record, it only counts as 1.
My database structure looks like this:
{
"external_userid" : "EXID1",
"follow_user" : [
{
"userid" : "USERID1",
"tags" : [
{
"tag_id" : "TAG1"
}
]
},
{
"userid" : "USERID2",
"tags" : [
{
"tag_id" : "TAG1"
},
{
"tag_id" : "TAG2"
}
]
}
]
},
{
"external_userid" : "EXID2",
"follow_user" : [
{
"userid" : "USERID1",
"tags" : [
{
"tag_id" : "TAG2"
}
]
}
]
}
Here's my query:
[
{ "$unwind": "$follow_user" }, { "$unwind": "$follow_user.tags" },
{ "$group" : { "_id" : { "follow_user᎐tags᎐tag_id" : "$follow_user.tags.tag_id" }, "COUNT(_id)" : { "$sum" : 1 } } },
{ "$project" : { "total" : "$COUNT(_id)", "tagId" : "$_id.follow_user᎐tags᎐tag_id", "_id" : 0 } }
]
What I expected:
{
"total" : 1,
"tagId" : "TAG1"
},
{
"total" : 2,
"tagId" : "TAG2"
}
What I get:
{
"total" : 2,
"tagId" : "TAG1"
},
{
"total" : 2,
"tagId" : "TAG2"
}
$set - Create a new field follow_user_tags.
1.1. $setUnion - To distinct the value from the Result 1.1.1.
1.1.1. $reduce - Add the value of follow_user.tags.tag_id into array.
$unwind - Deconstruct follow_user_tags array field to multiple documents.
$group - Group by follow_user_tags and perform total count via $sum.
$project - Decorate output document.
db.collection.aggregate([
{
$set: {
follow_user_tags: {
$setUnion: {
"$reduce": {
"input": "$follow_user.tags",
"initialValue": [],
"in": {
"$concatArrays": [
"$$value",
"$$this.tag_id"
]
}
}
}
}
}
},
{
$unwind: "$follow_user_tags"
},
{
$group: {
_id: "$follow_user_tags",
total: {
$sum: 1
}
}
},
{
$project: {
_id: 0,
tagId: "$_id",
total: 1
}
}
])
Sample Mongo Playground
I have the following documents:
{ "_id" : ObjectId("5d9db4462034bf17454d7d33"), "name" : "Product1", "cost_oneoff" : "1", "cost_monthly" : "1", "margin_oneoff" : "1", "margin_monthly" : "1", "price_oneoff" : "1", "price_monthly" : "1" }
{ "_id" : ObjectId("5d9dc2f2d8e17309b46f9b03"), "name" : "Product2", "cost_oneoff" : "0", "cost_monthly" : "1", "margin_oneoff" : "0,5", "margin_monthly" : "0,5", "price_oneoff" : "0", "price_monthly" : "2" }
I want the sum of e.g. cost monthly with the following statement:
{ "_id" : null, "total" : 0 }
Can someone help me?
db.service_items.aggregate([
{ $match: {$or: [{"_id": ObjectId("5d9db4462034bf17454d7d33")},{"_id": ObjectId("5d9dc2f2d8e17309b46f9b03")}]}},
{ $group:
{_id: null,
total: {
$sum: "$cost_monthly"
}
}
}
])
Result:
{ "_id" : null, "total" : 0 }
The desired answer is 2
The $sum operator only works on an integer. According to the docs it ignores non-numeric values. You seem to have them stored as a string. Change cost_monthly to an integer and you should get the desired result:
"cost_monthly" : 1
You can check it out here.
Like #silencedogood said, The $sum operator only works on an integer. We need to convert the string to a numeric value using $toInt operator.
The following is an example:
db.service_items.aggregate([
{
$match: {
$or: [
{
"_id": ObjectId("5d9db4462034bf17454d7d33")
},
{
"_id": ObjectId("5d9dc2f2d8e17309b46f9b03")
}
]
}
},
{
$group: {
"_id": null,
"total": {
$sum: {
$toInt: "$cost_monthly"
}
}
}
}
])
Note: The $toInt is introduced in Mongo v4.0
I've searched but could not find an answer to my problem. I need to count the occurences of the field "nationalCode". I've got a collection with this sample structure in MongoDB:
{
"_id" : ObjectId("5d7519cc6c17d65d4983f048"),
"origin" : "Base1",
"topic" : [
{
"nationalTopic" : {
"nationalCode" : 26
},
"dateTime" : NumberLong(20120927000000)
},
{
"nationalTopic" : {
"nationalCode" : 132
},
"dateTime" : NumberLong(20120927000000)
},
{
"nationalTopic" : {
"nationalCode" : 26
},
"dateTime" : NumberLong(20120927000000)
},
{
"nationalTopic" : {
"nationalCode" : 26
},
"dateTime" : NumberLong(20121005000000)
}
]
}
I've used the following code (I tried many variations of it, but none of them got me the right results):
db.processos.aggregate(
[
{ "$unwind": "$topic" },
{"$match": {"origin": "Base1"}},
{"$group": { "_id": { nationalCode: "$topic.nationalTopic.nationalCode", "count": { "$sum": 1 }} } }
]
)
I'm expecting something like this:
{
"_id" : {
"nationalCode" : 26,
"count" : 3.0
}
}
/* 2 */
{
"_id" : {
"nationalCode" : 132,
"count" : 1.0
}
}
You should extract the count element from the _id.
The following query worked for me.
db.data.aggregate(
[
{ "$unwind": "$topic" },
{"$match": {"origin": "Base1"}},
{"$group": { _id: { "nationalCode": "$topic.nationalTopic.nationalCode" },
"count": {$sum: 1} }
}
]
)
just do it with $project to change your format
do it like this
MongoDB Enterprise >
db.ggg.aggregate(
[
{$unwind:"$topic"},
{"$match": {"origin": "Base1"}},
{"$group": { "_id": { nationalCode: "$topic.nationalTopic.nationalCode"},
"count": { "$sum": 1 } }},
{$project :{"_id.nationalCode":1,"_id.count":"$count"}}
]
)
here it the result !
{ "_id" : { "nationalCode" : 26, "count" : 3 } }
{ "_id" : { "nationalCode" : 132, "count" : 1 } }
How can I group by ID and Month in MongoDB?
My data looks like this:
{
"_id" : ObjectId("597225c62e7cbfc9a0b099f8"),
"LogId" : NumberInt(17351963),
"EntryId" : NumberInt(22),
"Date" : "2013-08-11 00:00:00",
"LogTypeId" : NumberInt(6),
"Count" : NumberInt(1),
"EntryType" : NumberInt(1)
}
{
"_id" : ObjectId("597225c62e7cbfc9a0b099f9"),
"LogId" : NumberInt(17352356),
"EntryId" : NumberInt(23),
"Date" : "2013-08-11 00:00:00",
"LogTypeId" : NumberInt(6),
"Count" : NumberInt(2),
"EntryType" : NumberInt(1)
}
{
"_id" : ObjectId("597225c62e7cbfc9a0b099fa"),
"LogId" : NumberInt(17360483),
"EntryId" : NumberInt(28),
"Date" : "2013-08-11 00:00:00",
"LogTypeId" : NumberInt(6),
"Count" : NumberInt(1),
"EntryType" : NumberInt(1)
}
My simplified aggregation query runs without errors, but it doesn't group:
db.log.aggregate([
{"$group":{"_id":"$EntryId", "Count":{"$sum":"$Count"}}},
{"$sort": {"EntryId": 1}}
])
Ultimately, I want to group by EntryID and the month of the date column.
First of all "convert your strings to date" with a very simple operation:
let ops = [];
db.log.find().forEach(doc => {
ops.push({ "updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { "Date": new Date(doc.Date.replace(" ","T")) } }
}});
if ( ops.length >= 500 ) {
db.log.bulkWrite(ops);
ops = [];
}
});
if ( ops.length > 0 ) {
db.log.bulkWrite(ops);
ops = [];
};
Then run the new aggregate:
db.log.aggregate([
{ "$group": {
"_id": {
"EntryId": "$EntryId",
"year": { "$year": "$Date" },
"month": { "$month": "$Date" }
},
"Count": { "$sum": 1 }
}},
{ "$sort": { "_id": 1 } }
])
Also noting that even a "compound _id" like this one will sort correctly to it't numeric values.
I have analytics collection with the below sample data.
{ "_id" : ObjectId("55f996a4e4b0cc9c0a392594"), "action" : "apiUploadFile", "assetId" : "55f996a4e4b0cc9c0a392593" },
{ "_id" : ObjectId("5603d384e4b0cf75af10be88"), "action" : "agAsset", "assetId" : "55f996a4e4b0cc9c0a392593"},
{ "_id" : ObjectId("5603d395e4b0cf75af10becc"), "action" : "aAD", "assetId" : "55f996a4e4b0cc9c0a392593" },
{ "_id" : ObjectId("5603d395e4b0cf75af10becd"), "action" : "mobCmd", "assetId" : "55f996a4e4b0cc9c0a392593", sessionId : "123"},
{ "_id" : ObjectId("5603d395e4b0cf75af10bece"), "action" : "mobCmd", "assetId" : "55f996a4e4b0cc9c0a392593", sessionId : "1234" },
{ "_id" : ObjectId("5603d395e4b0cf75af10becf"), "action" : "mobCmd", "assetId" : "55f996a4e4b0cc9c0a392593", sessionId : "1234" }
I need find sum of analytics group by 'assetId' and then for each 'action' type. I have come up with the below query
db.analytics.aggregate(
[
{
$match : {
'assetId' : { "$ne": null }
}
},
{$group :{
_id:
{
assId:'$assetId'
},
viewCount:{
$sum:{
$cond: [ { $eq: [ '$action', 'agAsset' ] }, 1, 0 ]
}
},
sessionCount:{
$sum:{
$cond: [ { $eq: [ '$action', 'mobCmd' ] }, 1, 0 ]
}
}
}
}]
)
This works great except for the fact that I can not find the 'sessionCount' using distinct 'sessionId'. For example here is the current output
{ "_id" : { "assId" : "55f996a4e4b0cc9c0a392593" }, "viewCount" : 1, "sessionCount" : 3 }
The expected output is
{ "_id" : { "assId" : "55f996a4e4b0cc9c0a392593" }, "viewCount" : 1, "sessionCount" : 2 }
I need find the sessionCount for action='mobCmd' and has distinct values for sessionId. How can use distinct inside $sum operation of the 'sessionCount' section?
You will need to group your documents on a compound _id field.
db.collection.aggregate([
{ "$match": { "assetId": { "$ne": null }}},
{ "$group": {
"_id": { "assId": "$assetId", "sessionId": "$sessionId" },
"viewCount": {
"$sum": {
"$cond": [
{ "$eq": [ "$action", "agAsset" ] },
1,
0
]
}
},
"sessionCount": {
"$sum": {
"$cond": [
{ "$eq": [ "$action", "mobCmd" ] },
1,
0
]
}
}
}}
])
Which yields:
{ "_id" : { "assId" : "55f996a4e4b0cc9c0a392593", "sessionId" : "1234" }, "viewCount" : 0, "sessionCount" : 2 }
{ "_id" : { "assId" : "55f996a4e4b0cc9c0a392593", "sessionId" : "123" }, "viewCount" : 0, "sessionCount" : 1 }
{ "_id" : { "assId" : "55f996a4e4b0cc9c0a392593" }, "viewCount" : 1, "sessionCount" : 0 }
Or use the $addToSet operator to return an array of unique sessionId and $unwind the array then regroup your documents.
db.collection.aggregate([
{ "$match": { "assetId": { "$ne": null }}},
{ "$group": {
"_id": "$assetId",
"sessionId": { "$addToSet": "$sessionId" },
"viewCount": {
"$sum": {
"$cond": [
{ "$eq": [ "$action", "agAsset" ] },
1,
0
]
}
}
}},
{ "$unwind": "$sessionId" },
{ "$group": {
"_id": "$_id",
"viewCount": { "$first": "$viewCount" },
"sessionCount": { "$sum": 1 }
}}
])
Which returns:
{ "_id" : "55f996a4e4b0cc9c0a392593", "viewCount" : 1, "sessionCount" : 2 }