$match comparing one date field to another in mongoDB aggregate query - mongodb

I have a field called file_date, and in the start of the query I've set a new field called start_date which is 10 days back using:
{ $set: { start_date:{ $subtract: [ "$$NOW", 10*24*60*60*1000 ] } } }.
I want to use $match to find all the results where file_date is bigger then start_date.
I've tried using $gte but I can't seem to get the right syntax.
I'm using mongo 4.2 so I cant use SubstructDate
Thanks for any help
Changing the dates to strings using $toString.
using $gte

Related

How to get the last unique transactions from a collection in MongoDB

I have a collection that contains the following fields: agentId, postBalance, preBalance, etc. I want to fetch the last unique record for an agent that contains the field stated earlier based on a date filter.
db.transaction.find(
{
"createdAt" : {
"$gte": ISODate("2022-09-01T00:00:00Z"),
"$lt": ISODate("2022-09-02T00:00:00Z")
}
},
{
“agentId”: 1,
“walletBalance”: 1
}
)
The query above returns duplicate values and not the latest one. How best do I optimise this query. I am using Mongo Compass so I don't mind any query that comes in that format. I have read up on $last, $natural but they don't seem to solve my issue.
Have you tried to add sort by "createdAt" and limit of 1, or just using findOne method with same sort?

Mongodb shell aggregate query comparing dates not returning results

I cant spot what the issue here is. This returns nothing
db.mycoll.aggregate([
{$project:{CreatedAt:"$CreatedAt",Now:"$$NOW",DateFloor:{$add:["$$NOW",-24*60*60000]}}},
{$match:{CreatedAt:{$gte:"$DateFloor"}}}
])
But this returns results - substituting DateFloor with actual value
db.mycoll.aggregate([
{$project:{CreatedAt:"$CreatedAt",Now:"$$NOW",DateFloor:{$add:["$$NOW",-24*60*60000]}}},
{$match:{CreatedAt:{$gte: ISODate("2020-04-28T23:17:56.547Z")}}}
])
Issue with your query is when you're doing :
{$match:{CreatedAt:{$gte:"$DateFloor"}}}
You're actually checking for documents where CreatedAt field's value to be greater than input string value "$DateFloor", So $match is not considering "$DateFloor" as another field in the same document rather it's considering it as a string value. So to compare two fields from same document you need to use $gte with $expr (which will let you use aggregation expressions within the query language).
{
$match: {
{
$expr: {
$gte: ["$CreatedAt", "$DateFloor"];
}
}
}
}
So you might get confused when I say aggregation expressions & why $gte needs to be wrapped inside $expr - In your actual query $gte refers to comparison operator in MongoDB but in this above query $gte refers to aggregation pipeline operator where both technically does the same but which is what needed to compare two fields from same document.

Mongo 4.2 query base on date

I need to query Mongo using the FIND function, I can't use the aggregate function.
My documents are like this:
{
"name": "Tom",
"priDate":2010-04-11T00:00:00.000Z
}
The query I would like to make is:
Find all documents where ("priDate" + 1 year) is lte today.
Is it possible to do this without using an aggregation query? I can't use the field value in find ..
The query that I would need, I think, would be like this one I made:
db.system.profile.find({
"priDate" :
{
$gte: new Date(ITSELF + 1 year??) ,
$lt : new Date()
}
})
Can you help me?
many thanks, i'm going crazy :)
see if this works:
db.collection.find(
{
$expr: {
$lte: ['$priDate', { $subtract: ['$$NOW', 31536000000] }]
}
}
)
https://mongoplayground.net/p/QJ3BbHTQlgh
Adding "1 year" can be be difficult because of leap years or daylight-saving-times.
I suggest moment.js, then solution would be
db.system.profile.find(
{
priDate: {
$gte: moment().add(1, "year").toDate(),
$lt: moment().toDate()
}
}
)
However priDate >= "today + 1 year" AND priDate < "today" is not possible. Change the condition according to your needs.
MongoDB stores dates as milliseconds since epoch, so you can advance a date one year by adding the number of milliseconds in a year using $add inside $expr, then test with $lte:
db.system.profile.find({$expr:{$lte:[{$add:["$priDate",31536000000]},new ISODate()]}})
Note that this will be off by a day around leap year unless you adjust the number of milliseconds for that.
You expressed the constraint that you cannot use aggregate, but with $expr in Mongo 3.6 onwards, you can use any and all aggregation operators in a find query as well.
https://docs.mongodb.com/manual/reference/operator/query/expr/#definition

How can I make a time-relative mongodb view pipeline?

I want to make a mongodb view called "orders4H" that always returns documents from our "orders" collection that have a createdAt field value that is <= NOW-4hours. Then, any tool that is using the "orders4H" view as a collection source will always get the most current order data for the last 4 hours. The view creation requires an aggregation pipeline. However, I cannot figure out how to make a pipeline that will $match on a relative date.
In mongodb 4.2 they added an aggregation system variable called NOW which seems like it would be the thing to use, if only I could get it to work in a query document. I can use it to make new fields, for example, if I put timeNow: "$$NOW" in a $addFields stage, I get a new field with the current datetime. Now I want to use this "$$NOW" in a query evaluation.
Short version of question - how can I write a $match pipeline stage that will perform a server-time-relative comparison with a datetime field from the document?
MongoDB tickets imply that this support has been added ... but I cannot figure out how to use the $$NOW in a query. Anyone out there know how to do this?
Here are the relevant tickets that I found:
https://jira.mongodb.org/browse/SERVER-37713
https://jira.mongodb.org/browse/SERVER-23656
With help from mongodb tech support, I was able to get a $match stage that works with mongodb 4.2 to make a time-relative query:
[
{ $match:
{ $expr:
{ $gt: [
"$_created_at",
{ $subtract: [ "$$NOW", 4 * 60 * 60 * 1000] } ]
}
}
}
]

How to extract the creation date of _id and add it as a new field using the aggregation framework?

I have been trying for a while to extract the insertion date of a mongodb document and add it as a new field to the same document.
I'm trying to do it using the mongo and mongo shell aggregation framework without getting good results.
Here is my query
db.getCollection('my_collection').aggregate(
[
{
$match: {
MY QUERY CRITERIA
}
},
{
$addFields: { "insertTime": "$_id.getTimestamp()" }
}
]
)
I am trying to extracr insertion time from _id using the function getTimestamp() but for sure there is somtehing about aggregation framework syntax that I am missing because I can not do what I am trying to do in my query.
This works perfect:
ObjectId("5c34f746ccb26800019edd53").getTimestamp()
ISODate("2019-01-08T19:17:26Z")
But this does not work at all:
"$_id.getTimestamp()"
What I am missing?
Thanks in advance