Slow $group in mongodb - mongodb

I am working to fetch data from mongodb using $group. I have modified my query to
db.mydata.aggregate([{ $match: {"CreatedOn": {$lte: ISODate("2015-10-27T03:45:09Z"),
"$gte": ISODate("2015-09-09T07:37:27.526Z")}} },
{"$group" : { "_id" : "$myIP" , "total" : { "$sum" : "$SuccessCount"}}},
{ "$project" : { "myIP" : "$_id" , "_id" : 0 , "Total" : "$total"}},
{ "$sort" : { "Total" : -1}}, { "$limit" : 10}])
But it is taking more than 2 minute to execute, even for small amount of data. I have created index for CreatedOn. I have also created index for myIP.
I have document structure like
{ "_id" : ObjectId("55d33d7045cedc287ed840a3"),
"myIP" : "10.10.10.1","SuccessCount" : 1,
"CreatedOn":ISODate("2015-10-27T03:45:09Z")
}
I want success count's by all myIP's with maximum on top.

Related

Tried limiting the Group By data on mongo db 3.0

I have tried limiting the Group by data on Mongo DB 3.0 but seems like there is no proper option to do this.
I want to display 5 latest records for each day based on this date dateCreated which is in array and corresponding records count/day
db.entries.find().limit(1).pretty();
{
"_id" : "bd348fb4dd38dd7a2",
"className" : "com.model.Entry",
"name" : "yQLs3T5NCJocPlOPuLgyEkQ9",
"description" : "4Z09BNPQNFhFiMbjqL RWC5SMs0d0XzogqdNmjk5dx1mw9roHgRrl8ljbHo16p1WTlNYU",
"account" : DBRef("accounts", "248a3-448b-a912-6573f23d34a5"),
"iconUrl" : "gA9QTuqYv9wZq1xKM37jdL",
"userCreatedBy" : DBRef("users", "8044-45d2-8567-a6cb808ce164"),
"timezone" : "Atlantic/Faroe",
"globalAccess" : false,
"tags" : [
{
"_id" : "8926079483331",
"category" : "PPq5k",
"value" : "NdKFQq",
"description" : "uDQVnhJ2tu5XWHinb",
"origin" : "User",
"dateCreated" : ISODate("2021-07-16T18:20:41.731Z"),
"dateModified" : ISODate("2021-07-16T18:20:53.319Z"),
"externalId" : "xkblzrwE"
}
{
"_id" : "89389483331",
"category" : "PPe5k",
"value" : "NdKFQq",
"description" : "uDQVnhJ2tu5XWHinb",
"origin" : "User",
"dateCreated" : ISODate("2021-07-16T18:20:41.731Z"),
"dateModified" : ISODate("2021-07-16T18:20:53.319Z"),
"externalId" : "xkblzrwE"
}
]}
Output I'm expecting this :
[2021-07-16 (Date)-> (5 Latest Entries) , 2 (total records for that day) ]
I have tried using below solution
How to get lastest N records of each group in mongodb?
and slice is not available on mongo 3.0 i'm kind of stuck here
I'm not sure you can use aggregation but below aggregation can give you the result you wanted.
db.collection.aggregate([
{
"$unwind": "$tags"
},
{
$match: {
"tags.dateCreated": {
"$gte": ISODate("2021-07-16")
}
}
},
{
"$replaceRoot": {
"newRoot": "$tags"
}
},
{
"$limit": 5
}
])
Playground
If you have any question feel free to ask me, please.

Problem in using indexes in aggregation pipeline

I have a query like this
db.UserPosts.aggregate([
{ "$match" : { "Posts.DateTime" : { "$gte" : ISODate("2018-09-04T11:50:58Z"), "$lte" : ISODate("2018-09-05T11:50:58Z") } } },
{ "$match" : { "UserId" : { "$in" : [NUUID("aaaaaaaa-cccc-dddd-dddd-5369b183cccc"), NUUID("vvvvvvvv-bbbb-ffff-cccc-e0af0c8acccc")] } } },
{ "$project" : { "_id" : 0, "UserId" : 1, "Posts" : 1 } },
{ "$unwind" : "$Posts" },
{ "$unwind" : "$Posts.Comments" },
{ "$sort" : {"Posts.DateTime" : -1} },
{ "$skip" : 0 }, { "$limit" : 20 },
{ "$project" : { "_id" : 0, "UserId" : 1, "DateTime" : "$Posts.DateTime", "Title" : "$Posts.Title", "Type" : "$Posts.Comments.Type", "Comment" : "$Posts.Comments.Description" } },
],{allowDiskUse:true})
I have a compound index
{
"Posts.DateTime" : -1,
"UserId" : 1
}
Posts and Comments are array of objects.
I've tried different types of indexes but the problem is it does not use my index in $sort stage. I changed the place of my $sort stage but wasn't successful. It seems it is working in $match but not set to $sort. I even tried 2 simple indexes on those fields and combination of 2 simple indexes and one compound index but none of them works.
I also read related documents in MongoDB website for
Compound Indexes
Use Indexes to Sort Query Results
Index Intersection
Aggregation Pipeline Optimization
Could somebody please help me to find the solution?
I solved this problem by changing my data model and moving DateTime to higher level of data.

Mongodb sort by sum of keys

I have a json document
{
{
"_id" : ObjectId("5715c4bbac530eb3018b456a"),
"content_id" : "5715c4bbac530eb3018b4569",
"views" : NumberLong(200),
"likes" : NumberLong(100),
"comments" : NumberLong(0)
},
{
"_id" : ObjectId("5715c4bbac530eb3018b4568"),
"content_id" : "5715c4bbac530eb3018b4567",
"views" : NumberLong(300),
"likes" : NumberLong(200),
"comments" : NumberLong(0)
},
{
"_id" : ObjectId("5715c502ac530ee5018b4956"),
"content_id" : "5715c502ac530ee5018b4955",
"views" : NumberLong(500),
"likes" : NumberLong(0),
"comments" : NumberLong(200)
}
}
How can we sort the document order by SUM("views", "likes", "comments")
something like in mysql
SELECT SUM(key1, key2, key3) AS key
FROM document
ORDER BY key
Thanks in advance.
First do a projection to obtain the sum of all the likes, views and comments, then sort based on that sum. I am considering group by content_id if is needed in the second snippet
db.test.aggregate([
{ $project : { "_id" : "$content_id", "total" : { $add : [ "$likes", "$views", "$comments"]}}},
{ $sort : { "total" : 1 }}
])
If you need a group operation if content_id can be duplicated
db.test.aggregate([
{ $project : { "_id" : "$content_id", "total" : { $add : [ "$likes", "$views", "$comments"]}}},
{ $group : { "_id" : "$_id" , totalPerId : { $sum : "$total" }}},
{ $sort : { "total" : 1 }}
])
Based on your test data, you will get:
{ "_id" : "5715c502ac530ee5018b4955", "totalPerId" : NumberLong(700) }
{ "_id" : "5715c4bbac530eb3018b4567", "totalPerId" : NumberLong(500) }
{ "_id" : "5715c4bbac530eb3018b4569", "totalPerId" : NumberLong(300) }

Aggregation query returning array of all objects for mongodb

I'm using mongo for the first time. I'm trying to aggregate some documents in a collection using the query below. Instead the query returns an object with a key "result" that contains an array of all the documents that fit with $match.
Below is the query.
db.events_2015_04_10.aggregate([
{$group:{
_id: "$uid",
count: {$sum: 1},
},
$match : {promo:"bc40100abc8d4eb6a0c68f81f4a756c7", evt:"login"}
}
]
);
Below is a sample document in the collection:
{
"_id" : ObjectId("552712c3f92ea17426000ace"),
"product" : "Mobile Safari",
"venue_id" : NumberLong(71540),
"uid" : "dd542fea6b4443469ff7bf1f56472eac",
"ag" : 0,
"promo" : "bc40100abc8d4eb6a0c68f81f4a756c7",
"promo_f" : NumberLong(1),
"brand" : NumberLong(17),
"venue" : "ovation_2480",
"lt" : 0,
"ts" : ISODate("2015-04-10T00:01:07.734Z"),
"evt" : "login",
"mac" : "00:00:00:00:00:00",
"__ns__" : "wifipromo",
"pvdr" : NumberLong(42),
"os" : "iPhone",
"cmpgn" : "fc6de34aef8b4f57af0b8fda98d8c530",
"ip" : "192.119.43.250",
"lng" : 0,
"product_ver" : "8"
}
I'm trying to get it all grouped by uid's with the total sum of each group... What is the correct way to achieve this?
Try the following aggregation framework which has the $match pipeline stage first and then the $group pipeline later:
db.events_2015_04_10.aggregate([
{
$match: {
promo: "bc40100abc8d4eb6a0c68f81f4a756c7",
evt: "login"
}
},
{
$group: {
_id: "$uid",
count: {
$sum: 1
}
}
}
])

MongoDB $ne in sub documents

{
"_id" : ObjectId("53692eb238ed04c824679f18"),
"firstUserId" : 1,
"secondUserId" : 17,
"messages" : [
{
"_id" : ObjectId("5369338997b964b81d579fc6"),
"read" : true,
"dateTime" : 1399403401,
"message" : "d",
"userId" : 1
},
{
"_id" : ObjectId("536933c797b964b81d579fc7"),
"read" : false,
"dateTime" : 1399403463,
"message" : "asdf",
"userId" : 17
}
]
}
I'm trying to select all documents that have firstUserId = 1 and also have sub documents
that have userId differnet ($ne) to 1 and read = false.
I tried:
db.usermessages.find({firstUserId: 1, "messages.userId": {$ne: 1}, "messages.read": false})
But it returns empty cause messages have both 1 and 17.
And also how to count subdocuments that have given case?
Are you trying to get the count of all the documents which are returned after your match criteria? If Yes, then you might consider using aggregation framework. http://docs.mongodb.org/manual/aggregation/
Something like below could be done to get you the counts:
db.usermessages.aggregate(
{ "$unwind": "$messages" },
{ "$match":
{ "firstUserId": 1,
"messages.userId": { "$ne" : 1},
"messages.read": false
}
},
{ "$group": { "_id" :null, "count" : { "$sum": 1 } } }
)
Hope this helps.
PS: I have not tried this on my system.