How to update a field of collection efficient in MongoDB? - javascript

I have dataset as
{"id":1,"Timestamp":"Mon, 11 May 2015 07:57:46 GMT","brand":"a"}
{"id":2,"Timestamp":"Mon, 11 May 2015 08:57:46 GMT","brand":"a"}
The expected result of data is
{"id":1,"Timestamp":ISODate("2015-05-11T07:57:46Z"),"brand":"a"}
{"id":2,"Timestamp":ISODate("2015-05-11T08:57:46Z"),"brand":"b"}
It means I want to revise the Timestamp in each row from string to ISODate
My current code is
db.tmpAll.find().forEach(
function (a) {
a.Timestamp = new Date(a.Timestamp);
db.tmpAll2.insert(a);
}
);
It runs sucessfully, but it will take couple minutes to run the code and it need to create a new collection. Is there any efficient way to do it?

You don't need to create new collection. Use the collection.save method to update your document.
db.tmpAll.find().forEach(function(doc){
doc.Timestamp = new Date(doc.Timestamp);
db.tmpAll.save(doc);
})

Related

Using moments js to create a date array

Does anyone know how i can use moment js , to create a dynamic dates array , that contains todays date and dates of next 9 days.
so im creating a scheduler that will run on some days(not yet specified) when it runs its supposed to prepare some reports on todays date and next 9 days, my idea is to create an array of dates and map through them but i cant figure out how to create such an array using moment js , any ideas ?
i checked some legacy code and they are using the following to get present date
const now = moment().add(-moment().utcOffset(), 'minutes').toDate()
I think this is a good candidate for a traditional for loop solution, using an offset and the moment .add method to build an array adding the offset as you go, ending up with a ten-day array where the first element at index 0 holds the value of your now variable.
const moment = require('moment')
const date = moment().add(-moment().utcOffset(), 'minutes').toDate()
const reportDates = [];
for (let dayOffset = 0; dayOffset < 10; dayOffset++) {
const nextDate = moment(date).add(dayOffset, 'days').toDate();
reportDates.push(nextDate)
}
console.log(reportDates)
Output when I ran this snippet on my machine (# ~10:22 Central US time):
[
2022-11-29T22:22:51.788Z,
2022-11-30T22:22:51.788Z,
2022-12-01T22:22:51.788Z,
2022-12-02T22:22:51.788Z,
2022-12-03T22:22:51.788Z,
2022-12-04T22:22:51.788Z,
2022-12-05T22:22:51.788Z,
2022-12-06T22:22:51.788Z,
2022-12-07T22:22:51.788Z,
2022-12-08T22:22:51.788Z
]
The moment.js vs other libraries is another discussion, and if at all possible to use a different library I would recommend date-fns to avoid any confusion in the future from the mutability built into moment objects.
Good luck!

Javascript overwrites the array in several places within an object [duplicate]

This question already has answers here:
Modifying a copy of a JavaScript object is causing the original object to change
(13 answers)
Closed 3 months ago.
Sorry for the strange title, but I've come across an issue that is plain weird. To give some background, i'm working on a booking system that takes a time range as an input from admin, generates available times based on it, and then reduces the available times based on already made bookings (i.e admin specifies availability from 10:00 to 12:00, booking has been made to 11:30, available times will be times = [10:00, 10:30, 11:00, 12:00]).
I have an object that contains per month for each day the available times.
availableTimesPerDay: {
1: ["10:00","10:30","11:00","11:30","12:00"],
2: ["10:00","10:30","11:00","11:30","12:00"],
3: ["10:00","10:30","11:00","11:30","12:00"],
....
}
Where the number represents the date for the given month.
Bookings are represented as an array of objects, format is:
bookedTimes = [
{
date: "2022-12-01T11:30:00.000+02:00"
}
];
I planned to have a function which would iterate through each booking and remove the availability for that time on a given date (based on example above, 11:30 would need to be removed from availableTimesPerDay[1] leaving the value for it as ["10:00","10:30","11:00","12:00"]
The function itself is defined as such:
function reduceAvailableTimesBasedOnDateTime(availableTimesPerDay,bookedTimes){
console.log(JSON.stringify(availableTimesPerDay));
bookedTimes.forEach((bookedDateObject) => {
let bookedDate = new Date(bookedDateObject.date);
// 1
let currentAvailableTimesOnDate = availableTimesPerDay[bookedDate.getDate()];
// ["10:00","10:30","11:00","11:30","12:00"]
let bookedTime = bookedDate.toLocaleTimeString('et');
// "13:30:00"
let time = bookedTime.substring(0,bookedTime.length - 3);
// "13:30"
let index = currentAvailableTimesOnDate.indexOf(time);
// 3
if (index > -1) {
currentAvailableTimesOnDate.splice(index, 1);
// ["10:00","10:30","11:00","12:00"]
}
})
console.log(JSON.stringify(availableTimesPerDay));
return availableTimesPerDay;
}
The way I understand this function is that i've extracted a specific array of available times into a new variable and removed a specific time from that array. I have done no modifications on an original data and I would expect at this stage the availableTimesPerDay to remain unmodified. However, when I run my code, the availableTimesPerDay is modified even though I do no operations with availableTimesPerDay object itself.
What's even stranger is that the modification is not just strictly done on the 1st element, but on all specific dates that have the same day of the week. Here's output from the console for the console.log(availableTimesPerDay) defined in the function (note that 11:30 value is removed on dates 1st of December, 8th of December, 15th of December etc.
booking-helper.js:94 {"1":["10:00","10:30","11:00","11:30","12:00"],"2":[],"3":[],"4":[],"5":[],"6":[],"7":[],"8":["10:00","10:30","11:00","11:30","12:00"],"9":[],"10":[],"11":[],"12":[],"13":[],"14":[],"15":["10:00","10:30","11:00","11:30","12:00"],"16":[],"17":[],"18":[],"19":[],"20":[],"21":[],"22":["10:00","10:30","11:00","11:30","12:00"],"23":[],"24":[],"25":[],"26":[],"27":[],"28":[],"29":["10:00","10:30","11:00","11:30","12:00"],"30":[],"31":[]}
booking-helper.js:105 {"1":["10:00","10:30","11:00","12:00"],"2":[],"3":[],"4":[],"5":[],"6":[],"7":[],"8":["10:00","10:30","11:00","12:00"],"9":[],"10":[],"11":[],"12":[],"13":[],"14":[],"15":["10:00","10:30","11:00","12:00"],"16":[],"17":[],"18":[],"19":[],"20":[],"21":[],"22":["10:00","10:30","11:00","12:00"],"23":[],"24":[],"25":[],"26":[],"27":[],"28":[],"29":["10:00","10:30","11:00","12:00"],"30":[],"31":[
What's even more interesting is that if I copy the same function to codepen with same data or call it directly from the browsers console it works as expected - it removes the specific time from a specific date.
The way I understand this function is that I've extracted a specific array of available times into a new variable and removed a specific time from that array. I have done no modifications on an original data and I would expect at this stage the availableTimesPerDay to remain unmodified.
But that's not what is happening. A mere assignment of an array to a new variable does not create a new array. The new variable will reference the same array. So whatever mutation you bring to that array will be visible whether you look at that array via currentAvailableTimesOnDate or via availableTimesPerDay[bookedDate.getDate()]: they are just different ways to see the same array object.
If you don't want that splice to affect availableTimesPerDay[bookedDate.getDate()], then you must take a copy:
let currentAvailableTimesOnDate = [...availableTimesPerDay[bookedDate.getDate()]];
What's even stranger is that the modification is not just strictly done on the 1st element, but on all specific dates that have the same day of the week.
This would suggest that you have initialise availableTimesPerDay with a similar misunderstanding, so that all entries in that array reference the same array. This could for instance happen when you had initialised it as follows:
let availableTimesPerDay = Array(7).fill( ["10:00","10:30","11:00","11:30","12:00"]);
This creates one array ["10:00","10:30","11:00","11:30","12:00"] and populates the outer array with duplicate references to that array.
You should solve that too, and do something like this:
let availableTimesPerDay = Array.from({length: 7}, () =>
["10:00","10:30","11:00","11:30","12:00"]
);
Now that array literal is evaluated 7 times, each time producing a new array.
It seems like you might be under the mistaken assumption that this code:
let currentAvailableTimesOnDate = availableTimesPerDay[bookedDate.getDate()];
makes a copy of the array and you are then operating on the copy, not the original array. But that's not the case. You're essentially just aliasing the same array and then operating on it. To demonstrate:
const availableTimesPerDay = {
1: ["10:00","10:30","11:00","11:30","12:00"],
2: ["10:00","10:30","11:00","11:30","12:00"],
3: ["10:00","10:30","11:00","11:30","12:00"],
};
const currentAvailableTimesOnDate = availableTimesPerDay[1];
currentAvailableTimesOnDate.splice(0, 100);
console.log(availableTimesPerDay[1]);
If you run this code in the browser console, it will log an empty array, even though you "do no operations with availableTimesPerDay object itself."
To copy the array, you have at least a few options:
const currentAvailableTimesOnDate = availableTimesPerDay[1].slice();
// OR
const currentAvailableTimesOnDate = [...availableTimesPerDay[1]];
// OR
const currentAvailableTimesOnDate = Array.from(availableTimesPerDay[1]);
Using any of the above code, you would then be operating on a copy of the array, not the original one.
Regarding the day-of-week thing, that sounds to me like you are using getDay() instead of getDate() somewhere, though I do not see that in your code, and in fact you say you do not see that in the browser console. I don't have a clear answer for that but could it be that at one point you had getDay() and you are accidentally running an older version of the code that is different from what you are showing here and testing in the console?

Filtering document ID using views?

I am using cloudant database to store my values and I specify my
document ID to be string+date(ddmmyy) (e.g foo071117). Recently I
need to filter the documents to show documents in the last 7 days
(e.g foo311017 to foo061117) and I have used views to do this. This is my code:
function (doc) {
var datearr = [];
var today = new Date()
for (var i =1; i<=7; i++){
var datesfull = new Date(today.getFullYear(), today.getMonth(), today.getDate() - i);
var dd = datesfull.getDate();
if (dd<10){
dd = '0'+dd;
}
var mm = datesfull.getMonth()+1;
if (mm<10){
mm ='0'+mm
}
var yy = datesfull.getFullYear().toString().substr(-2);
var dates = "foo" + dd + mm + yy;
datearr.push(dates);
}
if((datearr.indexOf(doc._id.slice(0,-1))>=0) || (datearr.indexOf(doc._id)>=0)){
emit(doc._id,doc);
}
}
The slice is for when my json files gets too big and I have to split the file into multiple files (e.g foo0711170, foo0711171)
This code works at the beginning as after running, cloudant view only showed 7 documents which I wanted. However, as the days passes, the old files remains instead of having just 7 documents. Is Cloudant supposed to refresh to show 7 documents in the View as specified in my code or is this due to how the data is stored?
*I can't query data for the past 7 days using URL as I am using powerBI which limits my ability to write a code to specify which document ID to extract so I can only use views as a filter
When you supply a design document to Cloudant with an index definition, the view is built and stored on disk. You may then query the view at a later time to get its results.
In your design document your are getting the time of "now", which in this case is the time when indexing is performed - not the time that the query is performed. It therefore cannot be used to extract data "in the last 7 days" (of the query time).
One solution would be to change the way your document _id is built. If you used: yyyymmdd+string, then your documents would be stored in date order because Cloudant has a primary index on the _id field.
You could then query the database's primary index, starting with a key 7 days in the past e.g.:
/mydb/_all_docs?startkey=20171101&include_docs=true

How to query the date in Bookshelf.js

I'm using the Bookshelf.js ORM and I need be able to query by date and having some issues.
here is a samples code snippet that I'm using.
this.model.query((q) => {
q.where('created_at', '>=', Date.now());
q.orderBy('created_at', 'DESC');
})
.fetch().then(function (model) {
socket.send(JSON.stringify(model));
});
The above code just returns a null or empty array.
Any ideas?
It is really a pity your query returns empty results, querying in the future is a very nifty feature to have.
But I think you want data created in the past, right? So try
this.model.query((q) => {
q.where('created_at', '<=', new Date());
q.orderBy('created_at', 'DESC');
})
.fetch().then(function (model) {
socket.send(JSON.stringify(model));
});
Note also Date.now() that gives the milliseconds elapsed since the UNIX epoch was replaced by new Date() that gives the proper current date/time.
Anyway, the criteria makes not much sense either because it basically means all rows. Unless, of course, you are looking after some bug on created_at column or filtering out NULL attributes.

How to create a query on a Date field in MongoDB using mongoose?

I am trying to query a collection in Mongo database, to get all record with Time field in a date range. Time is defined as Date in database.
My environment: Node.js, Express, Jade, javascript.
This is the javascript code:
var query = {};
var timeQuery = {};
timeQuery["$lt"] = new Date().toISOString();
query["Time"] = timeQuery;
console.log(query);
db.model('testruns').find(query).exec(function (err, testruns) {
console.log(testruns.length);
// doing something
});
the result printed to console:
{ Time: { '$lt': '2014-10-30T15:04:39.256Z' } }
0
The query returns 0 results (there should be more)
By the way... Running date queries from RoboMongo returns results, just the wrong ones. for example:
db.testruns.find({Time : {"$gte" : new Date("2014-10-30T15:13:37.199Z")}})
returns all records.
What I tried:
This one, that one, another one, mongoose documentation of course, and many more results from google.
Most of them give the same answer, none of them works for me. HELP!
as far I see you are not including the field to reference in the query, can you try this:
I assume your field name is 'time'
var date = new Date(); //or the date you want to compare
db.model('testruns').find({"Time":{"$lt":date}}).exec(function (err, testruns) {
console.log(testruns.length);
// doing something
});
The problem was related to a schema definition, not directly to this code. The code of the query was correct. a schema definition had this field(Time) as String, which caused MongoDB to try and find a string in a date field...

Categories