Why are dates in match aggregate query being ignored? - mongodb

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)

Related

MongoShell db query of string date is not working

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()

How can I manipulate a date field in an aggregation pipeline?

I'm trying to set the time from a Date field to the start of the day
function getDate(date){ return new Date(date.getYear(), date.getMonth(),
date.getDate(), 0,0,0); }
...
{"$project" : {
"_id" : getDate("$dt"),
...
If I send "$dt" I get TypeError: date.getYear is not a function as I'm passing a string,
If remove the quotation marks, I get Error: "$dt is not defined",
but if I set "$dt" as value for "_id" I get a correct ISO Date.
So how do I pass the date object to the function?
MongoDB's aggregation pipeline does not support JavaScript. To manipulate date values for results in the aggregation pipeline you need to use Date Aggregation Operators.
For example :
db.date.aggregate([
{ $project: {
_id: { $dateToString: { format: "%Y%m%d", date: "$dt" }}
}}
])
Assuming you have a document with a field called dt with a date value of ISODate("2017-07-01T10:01:23.344Z"), the result would look like:
{
"result": [
{
"_id": "20170701"
}
],
"ok": 1
}
Note: if you have multiple documents for the same day, this approach will create duplicate _id values in your results. You may want to project to a different field name or perhaps use a $group stage instead of $project if your intent is to combine values for the same day.

MongoDB group by date and fill zero counts

I would like to group my search results by date. The results are then also counted.
var fromDate = new Date(req.query.fromDate);
var toDate = new Date(req.query.toDate);
global.databaseStatistic.collection(global.ARTICLEPRESS).aggregate([
{
$match: {
article: { $in: articleIdArray },
date: { $gte: fromDate, $lte: toDate }
}
},
{
$group: {
"_id": {
"date": {
$dateToString: { format: "%d.%m.%Y", date: "$date" }
}
},
"count": { $sum: 1 }
}
}
])
This works perfectly, but I would also like to show all days that have a count of zero. It should be so displayed every day within an interval, also having a count of zero. How can I do that?
as it looks very trivial - it is not.
There is no way to have a reference sequence to compare with, even $lookup cannot help as this a kind of inner join type.
The way you could have this done is a kind of post process of result-set returned to mongoose.
The steps I have in mind could be:
create array of dates from req.query.fromDate to req.query.toDate formated in the same way as in query
remove entries in array which we have in result set
merge our array with count:0 and date
sort results (if needed)
any comments welcome!

Get all records with specified properties between a certain date range

I am passing in two dates formatted as MM-DD-YYYY which is a date range. I need to query all records within that range and include specified fields. I've had no luck.
Part of a record in Mongo:
{
"_id": "some ID",
"date": {
"$date": "2015-06-26T13:02:12.121Z"
},
Query:
var Start = '09-07-2015'
var End = '09-14-2015'
If I do:
var query = Order.find({
date : {
$lt : End,
$gt : Start
}
});
I get the full document within the week ranges as expected. However, I want to specify the fields to return rather than full document. So I've tried using grouping and project to specify those fields:
var query = Order.aggregate(
{
$match :
{
date: {
$gte: start,
$lt: end
}
},
$group:
{
cust_ID: '$request.headers.customer_id',
wholesaler_ID: '$request.headers.wholesalerID'
}
}
);
Likewise: I've also tried it using project to get the results I want. I thought maybe it won't match on a date string like 09-07-2015, so I included the ISO date directly. Still no luck... the query comes back undefined or empty:
var query = Order.aggregate(
{
$project:
{
date: 'date',
cust_ID: '$request.headers.custID',
wholesaler_ID: '$request.headers.wholesalerID'
}
},
{
$match :
{
date: {
$gte: "2014-12-09T21:02:56.872Z",
$lt: "2015-12-09T21:02:56.872Z"
}
}
}
);
var query = Order.find({
date : {
$lt : End,
$gt : Start
}}, {cust_ID:1, wholeseller_ID:1}
);
This will work.
I just tested this using Robomongo
db.getCollection('offerdb').find({time_posted:{$gt: '2015-10-21T21:40:04+05:30', $lte:'2015-12-14T05:53:14+05:30'}},{_id:1, merchant_id:1})
Works like a charm for me.
Try this command in mongo shell
use dbname
db.collection_name.find({date: {$gte: ISODate('2015-09-07 00:00:00'), $lte: ISODate('2015-09-14 23:59:59.999999')}},{'cust_ID':1,'_id':0,'wholeseller_ID':1})

Find data for specific date in mongodb

I wanted to find data for 2014-08-01 from MongoDB collection. Date in MongoDB is in ISO format.I wrote below query, but it gives me very huge number which i suspect is not the data for 1 day. Can some one let me know what is wrong with query.
sd is the key
db.history.count({sd:{$gte: new Date("2014-08-01")},sd:{$lt:new Date("2014-08-01")}})
Ranges can be specified using $gte and $lt in the same document portion:
db.history.count({ "sd": {
"$gte": new Date("2014-08-01"), "$lt": new Date("2014-08-02")
}})
Otherwise the argument are considered to be separate and a logical "and" condition. But really since you are using the same "key" in your "sd" field, this is not allowed in a JSON/BSON document and violates the "unique" keys rule for hash structures in general. So one condition overwrites the other and only one is applied.
That is why your result is wrong. Use as shown above instead.
await model.find(
{
$or:
[
{
createdDate:
{ $gte: new Date(startDate), $lte: new Date(endDate) },
},
{
createdDate:
{ $gte: new Date(startDate), $lte: new Date(endDate).setDate(new Date(endDate).getDate() + 1) },
},
],
},
)
Please assign value to startDate and endDate. The above example will help to find different data from different date as well as the same date
for example if your trying to fetch data from '2020-06-22' to '2020-07-02' you will get data from this date range, other your are trying to fetch data on the same date this code will work that mechanism also
Thank you