MongoDB get all documents with highest value in collection - mongodb

Context:
I have a MongoDB full of Documents like this:
[
{
"_id": "615dc97907f597330c510279",
"code": "SDFSDFSDF",
"location": "ABC1",
"week_number": 39,
"year": 2020,
"region": "NA"
},
....
{
"_id": "615dc97907f597330c51027a",
"code": "SDFSGSGR",
"location": "ABC1",
"week_number": 42,
"year": 2021,
"region": "EU"
},
....
{
"_id": "615dc97607f597330c50ff50",
"code": "GGSFHSFS",
"location": "DEF2",
"week_number": 42,
"year": 2021,
"region": "EU",
"audit_result": {
"issues_found": true,
"comment": "comment."
}
}
]
Problem
I am trying to write an aggregation which should return all object with the highest "week_number" and highest "year". So with the example above, I want to return the full documents of _id "615dc97907f597330c51027a" and "615dc97607f597330c50ff50".
I tried multiple approaches. like first sorting and then grouping but with no success.
currently I have something like this, which seemed logical, but it returns all documents not only the one with the highest week and year
[
{
'$match': {
'$expr': {
'$max': '$week_number',
'$max': '$year'
}
}
}
]

You can do the followings in an aggregation pipeline:
$group by year and week_number; push the _id into an array for future lookup
$sort by year: -1 and week_number: -1
$limit to get the first grouping, which is the one with max year and week_number
$lookup the original documents using the previously stored array of _id in step 1
$replaceRoot to get back the documents
Here is the Mongo playground for your reference.

Related

how to sort mongodb document to appear document with certain key value to appear first,

// i want to appear document with isFeatured:"true" at first
{ "_id": "625c13ea5c5d3f49f152783b",
"name": "helmet 1",
"description": "gold",
"category": [
"helmet"
],
"price": "25000",
"stock": 25,
"user": "",
"isFeatured": true // with this property to come first and "isFeatured:false" later
}
You can invoke sort on the cursor to sort the documents in myCollection on the isFeatured field in descending order.
db.myCollection.find().sort({ isFeatured: -1 })
Or on aggregation pipeline query
db.myCollection.aggregate([{ $sort: { isFeatured: -1 } }])

Aggregation: group date in nested documents (nested object)

I've a mongo database with user information. If new userdata is added I do a duplicate check and in case of a duplicate entry, I do not create a new document, but instead update the existing one with a nested node (under tracking) adding the timestamp and some other informations.
{
"_id": "5e95dee277dcc55e9d18bf1a",
"email": "test#test.com",
"tracking": [
{
"domain": "mydomain",
"subdomain": "",
"ip": "59.214.120.68",
"timestamp": "2020-03-21 20:06:12",
"externalID": "82"
},
{
"domain": "mydomain",
"subdomain": "",
"ip": "99.214.130.33",
"timestamp": "2020-03-26 18:43:01",
"externalID": "483"
},
{
"domain": "mydomain",
"subdomain": "",
"ip": "19.214.131.22",
"timestamp": "2020-03-26 18:48:42",
"externalID": "485"
}
]
}
Now I'm trying to aggregate the documents and group/count them by date. Is there any option how I can do this with diffrent number of nodes under tracking for each document?
You can do something like this.
{
$unwind: {
path: "$tracking",
preserveNullAndEmptyArrays: true
}
}, {
$group: {
_id: "$tracking.timestamp",
count: {
$sum: 1
}
}
}
It would be much better if you could store datetimes as actual datetime type and not string representations. But assuming you cannot for now, to group by the date component without the time (which is what I believe you seek) you can use substr:
db.foo.aggregate([
{$unwind: "$tracking"}
,{$group: {"_id": {$substr: [ "$tracking.timestamp", 0, 10] } , n: {$sum:1} }}
]);

sum key and group by key with Mongodb and Laravel

Having this collection -
{
"_id": "5b508587de796c0006207fa7",
"id": "1",
"status": "pending",
"updated_at": "2018-07-19 13:02:40",
"created_at": "2018-07-19 12:35:19"
},
{
"_id": "5b508587de796c0006207fa5",
"id": "2",
"status": "completed",
"updated_at": "2018-07-19 13:02:40",
"created_at": "2018-07-19 12:35:19"
},
I want to have a query that will sum the status key by the id key.
For example -
{
"id":"1",
"pending":"1"
}
I am using Laravel 5.5 with MongoDB
Here is a working MongoPlayground. Check out Mongo's reference for Aggregations, as well as the $group operator.
db.collection.aggregate([
{
$group: {
_id: "$status",
sumOfStatus: {
$sum: 1
}
}
}
])
EDIT: After proof-reading, I'm not really sure that was what you were looking for. This example will return your a list of statuses for each id such as:
[
{
"_id": "5",
"completed": 3,
"pending": 3
}
]
To do so, I'm leveraging theĀ $cond operator in order to conditionally $sum documents depending on their status value. One drawback is that you have to repeat this for each value. Not sure of a way around that.
Regarding the Laravel implementation, I'm definitely not a Laravel expert, but check out this answer which shows an example on how to access the aggregate() method.

Mongoose/MongoDB - Sort by highest occurrence

I am trying to sort my response based on the highest occurrence of a postID and within a date.
My collection structure:
[
{
"postID": "2",
"date": "2017-04-11 21:40:52",
},
{
"postID": "1",
"date": "2017-04-11 21:40:52",
},
{
"postID": "2",
"date": "2017-04-11 21:40:52",
},
{
"postID": "2",
"date": "2017-04-11 21:40:52",
},
]
So in this case, the highest occurrence is the postID: 2. So I want something like:
{
postID: 2,
postID: 1
}
Note: Remember that I need to search in between two dates as well.
Sorry if this is too obvious. I don't even know how to begin making the Mongo's/mongoose' find search.
My Stack:
Node with mongoose
MongoDB 3.2.5
Any input will help. Thanks
You can use the MongoDB aggregation framework to group on a specific property. Mongoose has a low-level wrapper around the aggregation framework.
You can $group with the postID as the _id which will give you the unique values for each. Then you can $sort. You can also use $project to rename the property back to postID if you prefer:
Collection.aggregate([
{$group: {_id: "$postID"}},
{$sort: {_id: -1}},
{$project: {postID: "$_id", _id: 0}}
]);

Sorting before doing GROUP BY in MongoDB

I have a mongo database for bug tracking. It contains 2 collections:
Project
{
"_id": 1,
"name": "My Project"
}
Bug
{
"_id": 1,
"project": 1,
"title": "we have a bug",
"timestamp": 1400215183000
}
On the dashboard, I want to display the latest bug of each project - up to total of 10.
So basically, when doing GROUP BY "project" field, I need to make sure it will always select the LATEST bug (by doing a pre-sort by "timestamp").
I'm not sure how to combine sorting and grouping together, thanks.
In order to get the "lastest" bug per project while limiting to 10 results:
db.collection.aggregate({
{ "$sort": { "timestamp": -1, "project": 1 } },
{ "$group": {
"_id": "$project",
"bug": {
"$first": {
"_id": "$_id",
"title": "$title",
"timestamp": "$timestamp"
}
}
}},
{ "$limit": 10 }
})
So the sorting is done by timestamp and project (as an optimization) then you do the $group and the $limit. The grouping here is just looking on the "boundaries" using $first, and just returning all of the rest of the document, which you may or may not need.
Try to actually restrict your "timestamp" range using $match first in order to optimize this.