MongoDB query with subtraction on time not working? - mongodb

{'field.timestamp': {'$lt': Date()}, 'field.timestamp': {'$gt': new Date(ISODate().getTime() - 1000 * 60 * 60) } }
returns:
"JSON parsing error: Invalid date format at line 1, col 83"

You forgot the new keyword as well as duplicating keys 'field.timestamp'. If you are querying a date range from now and 15 days ago, then the correct query should be:
var fifteenDaysAgo = new Date(),
today = new Date();
fifteenDaysAgo.setDate(fifteenDaysAgo.getDate() - 15);
db.my_collection.find({ 'field.timestamp': { '$lt': today, '$gt': fifteenDaysAgo } });

Related

meteorhacks:aggregate to group mongo documents

This Meteor server code tries to count all the records which are 4 months and newer with property size:'4', color:'white' but account all entires from any one user as one count, so no mater how many documents have been entered by the same user, the are all counted as one. but I am getting nothing in return. any ideas? thx
let date = new Date();
date.setMonth(date.getMonth() - 4);
let doc = UsageCol.aggregate([{
$match: {
createdAt: {
$gte: date,
$lte: new Date()
},
action: 'failBroadcast',
plate: plate
}
}, {
$group: {
_id: {
userId: "$userId"
},
count: {
$sum: 1
}
}
}]);
for (var i = 0; i < doc.length; i++) {
var obj = doc[i];
console.log(JSON.stringify(obj));
}
Alright I just wanted to clear some things up from this morning.
The only reason I recommended moment js was thinking we are storing the date in date type and there is no easy way to dynamically create date in UTC using java script date function
So now that we know you used Date.now() to save the dates, you don't need any moment js.
The correct syntax is
let dateToMillis = Date.now(); //The current millis from epoch.
let dateFrom = new Date(dateToMillis); // Use the current millis from epoch.
let dateFromMillis = dateFrom.setMonth(dateFrom.getMonth() - 4); // The millis 4 months ago from epoch.
Pass dateToMillis and dateFromMillis to aggregation query.

Convert dates from String format to Date format in mongodb

I have my birthDate in string format like this "2010-03-22". I want to convert it in the Date type in MongoDB.
What db.patient.update() function should I write ?
I want to calculate the age of each person.
I used the solution give on How do I convert a property in MongoDB from text to date type? but all the dates got converted to "1970-01-01T00:00:00.000Z".
db.collection.find().forEach(function(e){
e.fieldname = new Date(e.fieldname)
db.collection.save(e)
});
If you are using robomonogo use new ISODate instead of new Date
One approach you could take in converting the field to the correct date object would be by splitting the string on the given delimiter "-". Use parseInt() to convert the delimited strings into numbers, and the new Date() constructor builds a Date from those parts: the first part will be the year, the second part the month, and the last part the day. Since Date uses zero-based month numbers you have to subtract one from the month number.
The following demonstrates this approach:
var cursor = db.patient.find({"birthDate": {"$exists": true, "$type": 2 }});
while (cursor.hasNext()) {
var doc = cursor.next();
var parts = doc.birthDate.split("-");
var dt = new Date(
parseInt(parts[0], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[2], 10) // day
);
db.patient.update(
{"_id": doc._id},
{"$set": {"birthDate": dt}}
)
};
For improved performance especially when dealing with large collections, take advantage of using the Bulk API for bulk updates as you will be sending the operations to the server in batches of say 500 which gives you a better performance as you are not sending every request to the server, just once in every 500 requests.
The following demonstrates this approach, the first example uses the Bulk API available in MongoDB versions >= 2.6 and < 3.2. It updates all
the documents in the collection by changing the OrderDate fields to date fields:
var bulk = db.patient.initializeUnorderedBulkOp(),
counter = 0;
db.patient.find({"birthDate": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
var parts = doc.birthDate.split("-");
var dt = new Date(
parseInt(parts[0], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[2], 10) // day
);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "birthDate": dt}
});
counter++;
if (counter % 500 == 0) {
bulk.execute(); // Execute per 500 operations and re-initialize every 500 update statements
bulk = db.patient.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 500 != 0) { bulk.execute(); }
The next example applies to the new MongoDB version 3.2 which has since deprecated the Bulk API and provided a newer set of apis using bulkWrite():
var bulkOps = db.patient.find({"birthDate": {"$exists": true, "$type": 2 }}).map(function (doc) {
var parts = doc.birthDate.split("-");
var dt = new Date(
parseInt(parts[0], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[2], 10) // day
);
return {
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "birthDate": dt } }
}
};
})
db.patient.bulkWrite(bulkOps);

MongoDB String attribute to Date

I have a collection with around 500,0000 entries in MongoDB.
Each entry has an attribute Date in the following format:
"Date" : "21/01/2005"
I'd like to know how I can convert it in such a way to Date format, so I can then index it (old-new) and query for entries by year.
I have tried:
db.collection.find().forEach(function(element){
element.OrderDate = ISODate(element.OrderDate);
db.collection.save(element);
})
But this just seems to change the Date attribute to today's date, along with time in the following format:
"Date" : ISODate("2016-02-11T11:41:45.680Z")
Thank you in advance.
Convert the field to the correct date object by spliting the string on the given delimiter. Use parseInt() to convert the strings into numbers, and the new Date() constructor builds a Date from those parts: the third part will be the year, the second part the month, and the first part the day. Since Date uses zero-based month numbers you have to subtract one from the month number.
The following demonstrates this approach:
var cursor = db.collection.find({"OrderDate": {"$exists": true, "$type": 2 }});
while (cursor.hasNext()) {
var doc = cursor.next();
var parts = doc.OrderDate.split("/");
var dt = new Date(
parseInt(parts[2], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[0], 10) // day
);
db.collection.update(
{"_id": doc._id},
{"$set": {"OrderDate": dt}}
)
};
For improved performance especially when dealing with large collections, take advantage of using the Bulk API for bulk updates as you will be sending the operations to the server in batches of say 500 which gives you a better performance as you are not sending every request to the server, just once in every 500 requests.
The following demonstrates this approach, the first example uses the Bulk API available in MongoDB versions >= 2.6 and < 3.2. It updates all
the documents in the collection by changing the OrderDate fields to date fields:
var bulk = db.collection.initializeUnorderedBulkOp(),
counter = 0;
db.collection.find({"OrderDate": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
var parts = doc.OrderDate.split("/");
var dt = new Date(
parseInt(parts[2], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[0], 10) // day
);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "OrderDate": dt}
});
counter++;
if (counter % 500 == 0) {
bulk.execute(); // Execute per 500 operations and re-initialize every 500 update statements
bulk = db.collection.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 500 != 0) { bulk.execute(); }
The next example applies to the new MongoDB version 3.2 which has since deprecated the Bulk API and provided a newer set of apis using bulkWrite():
var bulkOps = db.collection.find({"OrderDate": {"$exists": true, "$type": 2 }}).map(function (doc) {
var parts = doc.OrderDate.split("/");
var dt = new Date(
parseInt(parts[2], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[0], 10) // day
);
return {
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "OrderDate": dt } }
}
};
})
db.collection.bulkWrite(bulkOps);

Finding Documents created today

So, In meteor, I am trying to count the number of documents created today. Obviouly the code below tries to match it to the time of the day along with the date.
var ct2 = Bids.find({$and:[{bidder:currentUser},{createdAt:Date()}]}).count();
How do I go about finding the number of documents for today ?
Thanks in advance.
You might need to do something like this
Query to get last X minutes data with Mongodb
var ct2 = Bids.find({
$and: [
{ bidder: currentUser },
{
createdAt: { $gt: new Date(Date.now() - (1000 * 60 * 60 * 24)) }
}
]
}).count();
By using moment js:
date=moment().add(-1,'days').toISOString();
val1 = checkdate1.substring(0, 11)
temp=val1+'23:59:59.'
val3=date.substring(20,25)
val4=temp+val3;
count = Bids.find({"createdAt": {$gt:new Date(val4)}}).count()

Doing range queries in Mongoose for Hour / Day / Month/ Year

Trying to figure out how to do this. Basically I want to sort by Hour / Day / Month / Year of my submissions.
Each submission has a created field which contains a Mongoose Date object in the form of "created" : ISODate("2013-03-11T01:49:09.421Z"). Do I need to compare against this in the find() conditions?
Here is my current query (I'm wrapping it in a count for pagination purposes FWIW so just ignore that part):
getSubmissionCount({}, function(count) {
// Sort by the range
switch (range) {
case 'today':
range = now.getTime();
case 'week':
range = now.getTime() - 7;
case 'month':
range = now.getTime() - 31; // TODO: make this find the current month and # of days in it
case 'year':
range = now.getTime() - 365;
case 'default':
range = now.getTime();
}
Submission.find({
}).skip(skip)
.sort('score', 'descending')
.sort('created', 'descending')
.limit(limit)
.execFind(function(err, submissions) {
if (err) {
callback(err);
}
if (submissions) {
callback(null, submissions, count);
}
});
});
Can someone help me figure this out? With that current code it just gives me all submissions regardless of a time range, so I'm obviously not doing something properly
I think, you are looking $lt(Less than) and $gt(Greater Than) operators in MongoDB.
By using above operators the result can be queried according to time.
I am adding possible solution below.
var d = new Date(),
hour = d.getHours(),
min = d.getMinutes(),
month = d.getMonth(),
year = d.getFullYear(),
sec = d.getSeconds(),
day = d.getDate();
Submission.find({
/* First Case: Hour */
created: { $lt: new Date(), $gt: new Date(year+','+month+','+day+','+hour+','+min+','+sec) } // Get results from start of current hour to current time.
/* Second Case: Day */
created: { $lt: new Date(), $gt: new Date(year+','+month+','+day) } // Get results from start of current day to current time.
/* Third Case: Month */
created: { $lt: new Date(), $gt: new Date(year+','+month) } // Get results from start of current month to current time.
/* Fourth Case: Year */
created: { $lt: new Date(), $gt: new Date(year) } // Get results from start of current year to current time.
})