Mongo date aggregation operators with ObjectId - mongodb

I'm trying to use the ObjectId as a creation date holder, and running into some problems when trying to do aggregation queries. In particular we want to use the date aggregation operators to group the documents by month, but that operator doesn't work with ObjectId apparently. Is there a way around it, or would I have to start using a separate CreationTime field per document?
Here is a query I was trying -
db.People.aggregate([
{
$match: {
$or: [{"Name":"Random1"}, {"Name":"Random2"}]
}
},
{
$project: {
Name: "$Name",
Year: {$year: "$_id"},
Month: {$month: "$_id"}
}
},
{
$group: {
_id: {Name: "$Name", Year: "$Year", Month: "$Month"},
TotalRequests: {$sum:1}
}
}
])

Right now, you need to keep a separate field as the Aggregation Framework can not deal with this yet. There is a server ticket at https://jira.mongodb.org/browse/SERVER-9406 to implement it so I suggest you vote for it (I just did).

Related

How to find and count MongoDB Compass by year?

I want to count how many data by createdAt per-year. For example i want to count how many data in 2021 (select with createdAt) and how many data in 2022 in MongoDB Compass.
I dont know how the query with the $project.
My createdAt data example: createdAt 2020-11-04T11:20:08.058+00:00
Try using $group and $sum:
db.collection.aggregate({
$group: {
_id: {
$dateToString: {
"date": "$createdAt",
"format": "%Y"
}
},
count: {
$sum: 1
},
}
})
Link to playground.

How to find all the the ['id'] by month in pymongo?

I have a huge dataset consisting of collections with fields like this
{"id":"f3fd1b6c",
"originalVersion":"v2",
"rotation":[{"0.5"},{"-0.5"},{"-0.5"},{"-0.5"}],
"scale":[{"1.0"},{""1.0"},{""1.0"}],
"translation":[{"-2.8820719718933105"},{"11.548246383666992"},{"0.0"}],
"timestamp":"2020-03-27T13:28:09.883+00:00"
I want to get all the field ids that were created in same month.
So far I have tried using "find" with exact timestamp query
db.collection.find({'timestamp':date})
But I want to get all the elements that were created in same month,
If you are going to search records by a given month, you can do a simple find with $month
db.collection.find({
$expr: {
$eq: [
{
$month: "$timestamp"
},
3
]
}
})
Here is the Mongo playground for your reference.
If you want to group by month and group the ids together, you can do like this.
db.collection.aggregate([
{
$group: {
_id: {
"$month": "$timestamp"
},
idsToFetch: {
"$push": "$id"
}
}
}
])
Here is the Mongo playground for your reference.

Trying to get previous day date but facing error: unknown group operator '$gte'

db.system.js.insertOne(
{
_id : "getPreviousDayDates" ,
value : function (){ return db.Smx_20213_ShiftOEEDaily.aggregate(
[
{
$group:
{
_id: "$machineName",
maxlogdate: { $max: "$logDate" }
}
}
]
); }
}
);
db.eval("getPreviousDayDates()")
//Getting Current Date from this collection, but I wants to get previous day, So firstly I am getting current date from maxlogdate and now I wants to take previous date so, that's why I wrote this query but facing the issue as: unknown group operator '$gte'
If you want to insert a new document, that contains a field that is retrieved from existing documents, you can use an aggregation pipeline with a $merge step:
db.collection.aggregate([
{$match: {machineName: "a"}},
{$group: {_id: 0, timestamp: {$max: "$timestamp"}}},
{$addFields: {data: newObjectToInsert}},
{$set: {"data.previousDate": "$timestamp"}},
{$replaceRoot: {newRoot: "$data"}},
{$merge: {into: "collection"}}
])
As you can see on this playground example.
First we $match all the documents with the same machineName. Then we $sort them according to the timestamp, and $limit to one, in order to have just the last value. Now we need to add our newObjectToInsert, $set the new field and $merge to insert to the collection.
If you want to subtract one day from the date, you can use:
{
$set: {"data.previousDate": {
$dateAdd: {
startDate: "$timestamp",
unit: "day",
amount: -1
}
}
}
},
instead of:
{$set: {"data.previousDate": "$timestamp"}},

MongoDB get only the last documents per grouping based on field

I have a collection "TokenBalance" like this holding documents of this structure
{
_id:"SvVV1qdUcxNwSnSgxw6EG125"
balance:Array
address:"0x6262998ced04146fa42253a5c0af90ca02dfd2a3"
timestamp:1648156174658
_created_at:2022-03-24T21:09:34.737+00:00
_updated_at:2022-03-24T21:09:34.737+00:00
}
Each address has multiple documents like of structure above based on timestamps.
So address X can have 1000 objects with different timestamps.
What I want is to only get the last created documents per address but also pass all the document fields into the next stage which is where I am stuck. I don't even know if the way I am grouping is correctly done with the $last operator. I would appreciate some guidance on how to achieve this task.
What I have is this
$group stage (1st stage)
{
_id: '$address',
timestamp: {$last: '$timestamp'}
}
This gives me a result of
_id:"0x6262998ced04146fa42253a5c0af90ca02dfd2a3"
timestamp:1648193827320
But I want the other fields of each document as well so I can further process them.
Questions
1) Is it the correct way to get the last created document per "address" field?
2) How can I get the other fields into the result of that group stage?
Use $denseRank
db.collection.aggregate([
{
$setWindowFields: {
partitionBy: "$address",
sortBy: { timestamp: -1 },
output: { rank: { $denseRank: {} } }
}
},
{
$match: { rank: 1 }
}
])
mongoplayground
I guess you mean this:
{ $group: {
_id: '$address',
timestamp: {$last: '$timestamp'},
data: { $push: "$$ROOT" }
} }
If the latest timestamp is also the last sorted by _id you can use something like this:
[{$group: {
_id: '$_id',
latest: {
$last: '$$ROOT'
}
}}, {$replaceRoot: {
newRoot: '$latest'
}}]

MongoDB: can't convert from BSON type String to Date (16006)

I am getting this exception from Mongodb Aggregation operation:
can't convert from BSON type String to Date (16006)).
I see other questions on the same topic but I am very much sure that the field "date" in the following code is saved as Date type field. Here is what I am trying to do:
db.schemes.aggregate([
{"$project": {
date_day: {$dayOfMonth: "$date"},
date_month: {$month: "$date"},
date_year: {$year: "$date"},
net_asset: "$net_asset"
}},
{"$match": {scheme_code: "ABC"}},
{$group: {
_id: {
date_month: "$date_month",
date_year: "$date_year"},
net_asset: {$first: "$net_asset"},
day_date: {$first: "$date_day"}
}
}
])
Here is a sample document:
db.schemes.findOne()
{
"_id": ObjectId("586a87d5ab0de166ea000001"),
"scheme_code": "H01",
"scheme_name": "ABC",
"date": ISODate("2016-12-28T00:00:00Z"),
"net_asset": 48.452,
"updated_at": ISODate("2017-01-02T17:03:17.264Z"),
"created_at": ISODate("2017-01-02T17:03:17.264Z")
}
Also please note that the error doesn't occur if last group operator is removed so it has something to do with that.
Any pointers on how to go about debugging this one would be appreciated.
Thanks.
Placing Match before the project fixed the issue.