I have documents in my mongodb collection that look like:
{
"gran": "Day",
"dix": NumberInt(80),
"y": NumberInt(2017),
},
{
"gran": "Month",
"dix": NumberInt(3),
"y": NumberInt(2017),
}
I want to add to those documents a from/to field, so they look like:
{
"gran": "Day",
"dix": NumberInt(80),
"y": NumberInt(2017),
"from": ISODate("2017-03-21T00:00:00.000+0000"),
"to": ISODate("2017-03-21T23:59:59.000+0000")
},
{
"gran": "Month",
"dix": NumberInt(3),
"y": NumberInt(2017),
"from": ISODate("2017-03-01T00:00:00.000+0000"),
"to": ISODate("2017-03-31T23:59:59.000+0000")
}
I wrote a javascript function that converts from granularities to dates:
function(year, index, gran) {
var fromToDates = {};
if (gran === "Day") {
var initDate = new Date(year, 0); // initialize a date in `year-01-01`
var currentDate = new Date(initDate.setDate(index)); // add the number of days
var dateFrom = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), 0, 0, 0);
var dateTo = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), 23, 59, 59);
fromToDates.from = dateFrom;
fromToDates.to = dateTo;
return fromToDates;
} else if (gran === "Week") {
var simple = new Date(year, 0, 1 + (index - 1) * 7);
var dow = simple.getDay();
print(dow);
var dateFrom = simple;
if (dow <= 4)
dateFrom.setDate(simple.getDate() - simple.getDay() + 1);
else
dateFrom.setDate(simple.getDate() + 8 - simple.getDay());
var dateTo = new Date(dateFrom);
dateTo.setDate(dateTo.getDate() + 6);
dateTo.setUTCHours(23);
dateTo.setUTCMinutes(59);
dateTo.setUTCSeconds(59);
fromToDates.from = dateFrom;
fromToDates.to = dateTo;
return fromToDates;
} else if (gran === "Month") {
var monthIndex = index - 1;
var initDate = new Date(year, monthIndex);
var dateFrom = new Date(initDate.getFullYear(), monthIndex, 1, 0, 0, 0);
var lastDayOfMonth = monthIndex + 1;
var dateTo = new Date(dateFrom.getFullYear(), lastDayOfMonth, 0, 23, 59, 59);
fromToDates.from = dateFrom;
fromToDates.to = dateTom;
return fromToDates;
} else if (gran === "Quarter") {
var dateFrom = new Date(year,index*3-3,1);
var dateTo = new Date(year,index*3,0, 23, 59, 59);
fromToDates.from = dateFrom;
fromToDates.to = dateTo;
return fromToDates;
}
else if (gran === "Year") {
var dateFrom = new Date(year, 0, 1, 0,0,0);
var dateTo = new Date(year, 11, 31, 23, 59, 59);
fromToDates.from = dateFrom;
fromToDates.to = dateTo;
return fromToDates;
}
}
For adding the two fields from/to I thought I can use this method:
db.reports.findAndModify({
query: { "from": {$exists: false}},
update: {
$set: {
"from": new Date(),
"to": new Date()
}
},
multi: true
})
Then I read around that I could do this:
db.reports.aggregate([
{
$match:
{
}
}
]).map(function(doc) {
var dates = dateIndexToDateWithFromTo(doc.y, doc.dix, doc.gran);
doc['from'] = dates.from;
doc['to'] = dates.to;
return doc;
})
but this is not really working. It does return the correct dates but of course it doesn't update them in the collection. Anyone has an idea how I can update my documents dynamically by using the script that I wrote?
I'm using mongodb version 3.2 so for everyone that will suggest to use $addFields in an aggregation pipeline, it's not possible, because it's not possible for me to update to 3.4 right now.