MongoShell db query of string date is not working - mongodb

I am trying to query my database on the date_recorded field, but the query give zero results. I'm using the MongoShell and have also tried it in Compass.
I've tried variations of $eq with ISODate and Date:
db.my_collection.find({ "date_recorded": { "$eq": new ISODate("2017-06-09T01:27:33.967Z") }}).count()
I have also tried variations of $gte with ISODate and Date:
db.my_collection.find({ "date_recorded": { "$gte": new Date("2017-06-09T01:27:33.967Z") }}).count()
Record is in the db, notice the highlighted field

Like #JohnnyHK said, the date_recorded is a string. To make a comparison, we either need to convert date_recorded to a date or compare is with a string.
The following queries can get us the expected output:
db.my_collection.find({
"date_recorded": {
$eq:"2017-06-09T01:27:33.967Z"
}
}).count()
db.my_collection.find({
$expr:{
$eq:[
{
$toDate:"$date_recorded"
},
new ISODate("2017-06-09T01:27:33.967Z")
]
}
}).count()

Related

Mongodb - Using a long number to filter a Date type field in aggregation

I'm trying to filter a collection on a date type field using a long number (number of ms since epoch) and can't seem to get it to work in a regular find() or an aggregation. What am I missing ?
TIA!
db.testColl.insertOne({_id:"test", createDate: ISODate("2022-12-26T01:00:00.000+0000")})
db.testColl.find( {createDate: {$gte : {$toDate:1608947820333} }} )
I think you can't use aggregate expression $toDate in find/match. Instead, try using it with $expr.
db.testColl.find({
$expr: {
$gte: [
"$createDate",
{
$toDate: 1608947820333
}
]
}
})

How to convert string to ISODate in mongodb and compare it with $$NOW

Here, In my mongo collection, the date type column data is stored as string. I have a view where I need to compare this date with current date and time $$NOW. Since my date is stored as string. The query is getting executed but not getting compared. I tried to convert this string to date type but the data changed like this 2022-05-23 1:28:36 quotes were gone. Tried to run same query, but getting an error.
sample data:
[{oldDate:"2022-05-23 1:28:36"}]
My query:
db.collection.aggregate([
{
"$match": {
$expr: {
$lt: [
"$oldDate",
"$$NOW"
]
}
}
}
])
If the data in db is in the form of ISODate("2022-05-23 1:28:36") then this query is working. But the actual data in my db for this column is in the form of string. Can anyone help me to convert this to ISODate() through code itself and make comparison work.
Use $toDate operator to convert date string to date.
db.collection.aggregate([
{
"$match": {
$expr: {
$lt: [
{
$toDate: "$oldDate"
},
"$$NOW"
]
}
}
}
])
Sample Mongo Playground

MongoDB v5.0.5 query using hour only

First occasion experimenting with dates and times in MongoDB.
Currently, I have correctly inserted UTC dates into my documents:
{
"Value": 10
"DateTime": {
"$date": "2013-08-23T08:00:00.000Z"
},
}
I want to query the data to return all of the 'value' and datetime fields for all documents in which the hour is 08. I have gotten as far as:
db.readings.aggregate([{$project:{hour:{$hour:"$DateTime"}}},{$match:{hour:{"$in":[08]}}}])
Which returns the _id and "hour": 8 for all matching entries but I'm confused at how to proceed. It seems an unnecessarily complicated way to search and so I wonder if I am barking up the wrong tree here? Admittedly, I am somewhat out of my depth so some guidance would be appreciated.
You can try $expr expression operator to use aggregation operators ($hour) in query,
$expr to use aggregation operators
$hour will return an hour from the date
$eq to match hour and input hour 8
db.collection.find({
$expr: {
$eq: [
{ $hour: "$DateTime" },
8
]
}
})
Playground

Mongodb Query to get only documents in specific days

In my mongodb table, I have 2 (relevant for this Q) columns: service, timestamp.
I want to query only rows with service=liveness and that those with timestamp of 12th Novermber 2020.
How can I do it, if timestamp field is of type Number (UNIX epoch number)..?
This is my query currently:
{ service: "liveness" }.
This is how the timestamp column looks like:
To query by two fields you only need this syntax:
db.collection.find({
"field1": yourField1Value,
"field2": yourField2Value
So, if your date is a Number instead of a Date you can try this query:
db.collection.find({
"service": "liveness",
"timestamp": 1600768437934
})
And should works. Example here.
Now, if the problem is parse 12th November 2020 to UNIX timestamp, then the easiest way is convert first the date in your app language.
Edit:
Also, I don't know if I've missunderstood your question but, here is another query.
db.collection.aggregate([
{
"$match": {
"service": "liveness",
}
},
{
"$project": {
"timestamp": {
"$toDate": "$timestamp"
}
}
},
{
"$match": {
"timestamp": {
"$gt": ISODate("1990-01-01"),
"$lt": ISODate("2060-01-01")
}
}
}
])
This query first match all documents with service as liveness, so the next stage is faster. Into $project the timestamp is parsed to Date so you can match again with your date.
Using $gt and $lt you can search by a whole day.
And also, if you can get the days into UNIX timestamp you can do this:
db.collection.find({
"service": "liveness",
"timestamp": {
"$gte": yourDay,
"$lt": nextrDay
}
})
Using $gte and $lt you ensure the query will find all values in the day.

Why are dates in match aggregate query being ignored?

I'm trying to run an aggregation statement in my mongo db. I have a document whose structure is (at least) as follows:
{
"_id": ObjectId,
"date": ISODate,
"keywordGroupId": NumberLong,
"ranking": NumberLong,
}
I would like to run an aggregation statement that aggregates the 'ranking' field for a given 'keywordGroupId' and a given 'date' interval.
I have been trying with the following aggregate command:
{
aggregate : "KeywordHistory",
pipeline : [
{ $match: { keywordGroupId: 75 , "$date": {$gte: ISODate("2013-01-01T00:00:00.0Z"), $lt: ISODate("2013-02-01T00:00:00.0Z")}} },
{ $group: { _id: { null }, count: { $sum: "$ranking" } } }
]
}
This command executes without errors and returns a result. If I try to change the value for the 'keywordGroupId' field, the command returns a different value, so I assume that the $match statement works for that field (NumberLong). Though, if I change the 'date' range and I specify a time interval for which I don't have any data in the database, it still returns a result (I would actually expect an empty result set). So I have to assume that the $match statement is ignoring the date interval specified.
Can anyone help me with this point?
Remove the $ prefix on the $date field of your $match:
{ $match: {
keywordGroupId: 75,
date: {$gte: ISODate("2013-01-01T00:00:00.0Z"), $lt: ISODate("2013-02-01T00:00:00.0Z")}
}},
You only use the $ prefix when the field name is used in a value, not as a key.
Sometimes ISodate does not works . so in Case if you want to match date using only "one" date the best way is:---
ex:-- Let a schema be:---
var storeOrder = new Schema({
store_name:{type:String, required:true},
date :{type:Date ,default:moment(new Date()).format('YYYY-MM-DD')},
orders : [{
vegetable : String,
quantity : Number,
price:Number
}]
});
mongoose.model('storeorder',storeOrder);
now to aggregate by matching date :--
storeOrder.aggregate([$match:{date :new Date("2016-12-26T00:00:00.000Z")} ])
**It is must to use new Date("2016-12-26T00:00:00.000z") instead of Date("2016-12-26T00:00:00.000z") because Date(your_date) !== new Date(your_date).
THANK YOU
The aggregate expects a Javascript Date Object and doesn't work otherwise.
new Date();
new Date(year, month, day);
Please note the month start with 0 and not 1 (Your January is 0 and December 11)