MongoDB how to fetch documents based on multiple dates - mongodb

I have a collection of events, each have a start date. I want to fetch data starting on specific dates only. How will i do that ? I found a lot of solutions for date ranges but this case is different. If client inputs two dates i need to fetch only the events starting on those two dates, no need of dates in between. I tried using $or, $in etc but no use. The below code will not work.
let query = {
startDate: {
$or: [
{
$gte: new Date("2018-05-10T00:00:00.000Z"),
$lt: new Date("2018-05-10T23:59:59.000Z")
},
{
$gte: new Date("2018-08-06T00:00:00.000Z"),
$lt: new Date("2018-08-06T23:59:59.000Z")
}
]
}
};

Found the answer.
let query = {
$or: [
{
startDate: {
$gte: new Date("2018-05-10T00:00:00.000Z"),
$lt: new Date("2018-05-10T23:59:59.000Z")
}
},
{
startDate: {
$gte: new Date("2018-08-06T00:00:00.000Z"),
$lt: new Date("2018-08-06T23:59:59.000Z")
}
}
]
};

Related

Mongo database query operation question on dates as string

Let’s say some external component inserts data into my mongo database with Field called “startDate”. They store the value as string in mongo db in format yyyymmdd-HHmmss.
Can I still run the date time queries to fetch documents between two dates ?
Will below work as expected for above scenario?
db.test.find({ startDate:{$gt: “20201121”, $lte: “20210121”}})
Yes, it will but not for the same end date. It'd be better to add a day to cater for trailing zeros.
//data
[
{
startDate: "20210101-010101"
},
{
startDate: "20210121-000000"
},
{
startDate: "20210121-010000"
}
]
// query 1 - not successful maybe
[
{
startDate: "20210101-010101"
},
{
startDate: "20210121-000000"
},
{
startDate: "20210121-010000"
}
]
//query 2, successful
db.collection.find({
startDate: {
$gt: "20201121",
$lt: "20210122"
}
})

Get document on subarray containing date between aggregation mongodb

Provided following collection:
[
{
events: [
{
triggers: [
{
date: "2019-12-12T23:00:00"
}
]
}
]
}
]
I want to be able to pull the documents that have any date in between a range of dates, let's say today and tomorrow.
Using following query:
db.collection.aggregate([
{
$match: {
"events.triggers.date": {
$gte: "2019-12-11T23:00:00.000Z",
$lt: "2019-12-12T23:59:00.000Z"
}
}
}
]);
However, when I do this, the query seems to be looking at any document that has any date greater than and any date lower than but not necessarily in the same "trigger" object.
Anyone got any idea how you can filter in a subarray like this (I do more in my query afterwards so a find will not work) and have the date search be subitem specific?
You are almost there, just some mistakes in your query. This should work:
db.collection.aggregate([
{
'$match': {
'$and': [
{"events.triggers.date": { '$gte': "2019-12-11T23:00:00.000Z" }},
{"events.triggers.date": { '$lt': "2019-12-11T23:00:00.000Z" }}
]
}
}
]);
So I found it eventually.
Those looking for the solution. Here it is:
elemMatch
db.collection.aggregate([
{
$match: {
"events.triggers": {
$elemMatch: {
"date": {
$gte: "2019-12-11T23:00:00.000Z",
$lt: "2019-12-12T23:59:00.000Z"
}
}
}
}
}
]);

Date range not working in aggregation pipeline, but works in find()

I am trying to filter data by a date range. Example return the data that was created no more than 14 days ago.
I can do this in find with the following:
{
$match: {
eventTime: { $gte: startTime.toDate(), $lte: endTime.toDate() }
}
}
eventTime is an ISO date as well as startTime and endTime
I am using an aggregation and a lookup and trying to implement the same thing:
{
$lookup:
{
from: "data",
let: { dataId: "$dataId", patientId: "$patientId" },
pipeline: [
{
$match:
{
$expr:
{
$and:
[
{ $eq: ["$patientId", patientId] },
{ $eq: ["$dataId", "$$dataId"] },
{ $gte: ["$eventTime", startTime.toDate()] },
{ $lte: ["$eventTime", endTime.toDate()] },
]
}
}
}
],
as: "data"
}
}
But no data results are returned. If I remove the dates I get all the correct data based on dataId and patient. so the join is working.. but somehow the date range is not.
Again both the eventTime and startTime and endTime are all ISO dates.
example :
let endTime = Moment(new Date());
let startTime = Moment().subtract(days, "days");
"eventTime": "2019-08-07T03:37:40.738Z"
startTime "2019-07-30T00:02:11.611Z"
endTime "2019-08-13T00:02:11.610Z"
End time is 'today'
so in the example here the data time is between the two dates and should be returned.
I looked there : https://docs.mongodb.com/manual/reference/operator/aggregation/gte/
and it should work.. but not the case
I tried:
{eventTime: { '$gte': new Date(startTime), $lte: new Date(endTime)}}
and I get:
MongoError: An object representing an expression must have exactly one field: { $gte: new Date(1564495211043), $lte: new Date(1565704811042) }
also tried:
{ eventTime: {'$gte': new Date(startTime)}}
and get:
MongoError: Expression $gte takes exactly 2 arguments. 1 were passed in.
also tried:
{ $eventTime: {'$gte': new Date(startTime)}}, {$eventTime: {'$lte': new Date(endTime)}}
and get: MongoError: Unrecognized expression '$eventTime'
Any insight would certainly be appreciated
I was able to get it working via toDate:
{
$match:
{
$expr:
{
$and:
[
{ $eq: ["$patientId", patientId] },
{ $eq: ["$dataId", "iraeOverallAlert"] },
{ "$gte": [ {$toDate: "$eventTime"}, startTime.toDate()] },
{ "$lte": [ {$toDate: "$eventTime"}, endTime.toDate()] },
]
}
}
},
Note: This was not needed in the find, but somehow was needed using aggregation. Makes no sense but yah for trial and error.

Two date find between two data in collection

I have below collection data in mongo db.
"enddate" : ISODate("2019-03-27T14:30:00.000Z"),
"date" : ISODate("2019-03-27T10:30:00.000Z"),
I have two date like start date "2019-03-26T19:30:00.000Z" and end date "2019-03-26T20:30:00.000Z"
I want to find above two date time period exits in collection or not.
Please help to make mongodb query.
advt.date = m.utc().toISOString();
advt.enddate = me.utc().toISOString();
advt.time = m.utc().toISOString();
advt.endtime = me.utc().toISOString();
var Query = Advertisement.find({
$or: [
{ $and:[{ date: { $gte: advt.date }, enddate:{ $lte: advt.enddate } }] } ,
{ $and:[{ enddate: { $gte: advt.date }, date:{ $lte: advt.enddate } }] }
],"ad_type":"splash", "isDeleted":false, "_id":{ $ne: advt._id }
});
You can use ObjectId.getTimestamp() for that purpose.
Also check this Link

Mongo query using aggregation for dates

In the following query I'm trying to find entries in my articles collection made in the last week, sorted by the number of votes on that article. The $match doesn't seem to work(maybe I dont know how to use it). The following query works perfectly, so its not a date format issue,
db.articles.find(timestamp:{
'$lte':new Date(),
'$gte':new Date(ISODate().getTime()-7*1000*86400)}
})
But this one doesn't fetch any results. Without the $match it also fetches the required results(articles sorted by votecount).
db.articles.aggregate([
{
$project:{
_id:1,
numVotes:{$subtract:[{$size:"$votes.up"},{$size:"$votes.down"}]}}
},
{
$sort:{numVotes:-1}
},
{
$match:{
timestamp:{
'$lte':new Date(),
'$gte':new Date(ISODate().getTime()-7*1000*86400)}
}
}
])
You are trying to match at the end of your pipeline, which supposes you have projected timestamp field, and you haven't done that.
I believe what you want is to filter data before aggregation, so you should place match at the top of your aggregation array.
Try this:
db.articles.aggregate([{
$match: {
timestamp: {
'$lte': new Date(),
'$gte': new Date(ISODate().getTime() - 7 * 1000 * 86400)
}
}
}, {
$project: {
_id: 1,
numVotes: {
$subtract: [{
$size: "$votes.up"
}, {
$size: "$votes.down"
}]
}
}
}, {
$sort: {
numVotes: -1
}
}])