Compare two Firestore Timestamps in Cloud Functions - node.js

I'm writing update function in Firestore and I want to compare two Timestamp. I've tried multiple things but not working. Can you point me correct way of comparing two Timestamp in firestore.
exports.updateFunction = functions.firestore
.document('xyz/{xyzId}')
.onUpdate((change, context) => {
var updatedXYZ = change.after.data();
var oldXYZ = change.before.data();
var newTimestamp = updatedXYZ.timing;
var oldTimestamp = oldXYZ.timing;
// I've tried following things but not working
var result = newTimestamp === oldTimestamp; // not working
var result = new Date(newTimestamp) - new Date(oldTimestamp); // not working
return true;
});
I want to check two Timestamp is same or not.

Consult the API docs for Firestore's Timestamp object. Timestamp has a method called isEqual() that will compare two timestamps.
var result = newTimestamp.isEqual(oldTimestamp);

You need to add this line
admin.firestore().settings( { timestampsInSnapshots: true })
in your index.js file.
After adding this line cloud function will read your timestamp field as Timestamp Datatype. Now you can compare two timestamps using
var result = newTimestamp.isEqual(oldTimestamp);

//I assume you have yourTimestampInMilliseconds
const currentTimestamp = Date.now();
console.log("(currentTimestamp <= yourTimestampInMilliseconds)= "+ (currentTimestamp <= yourTimestampInMilliseconds));
console.log("(currentTimestamp > yourTimestampInMilliseconds)= "+ (currentTimestamp > yourTimestampInMilliseconds));

Related

Retrieving a date from Firestore in Node.js

From the Firestore documentation on saving data of supported types, I red:
var docData = {
//...
dateExample: new Date("December 10, 1815"),
//...
}
};
db.collection("data").doc("one").set(docData).then(function() {
console.log("Document successfully written!");
});
This is what I use in my Cloud Functions to save various dates to Firestore.
It works great !
My problem comes when I need to retrieve those dates and post them as String to a third party API.
As far as I understood, in Firebase/Firestore, dates are stored as a Unix Timestamp.
I couldn't find anywhere (firebase doc, stackoverflow ...) how to convert it properly to a String.
I tried unsuccessfully the following:
function timeConverter(UNIX_timestamp){
var a = new Date(UNIX_timestamp * 1000);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear();
var month = months[a.getMonth()];
var date = a.getDate();
var hour = a.getHours();
var min = a.getMinutes();
var sec = a.getSeconds();
var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
return time;
}
admin.firestore().collection('users').doc(userId).get()
.then( (doc) => {
const user = doc.data();
const birthDate = user.birthDate;
const birthDateString = timeConverter(birthDate);
console.log(`birthDateString =${birthDateString}`);
// "birthDateString = NaN undefined NaN NaN:NaN:NaN"
});
First you can use toDate() to convert the Firebase timestamp to a Date object and then use the Date's object method toDateString() to convert it to a String.
const birthDate = user.birthDate.toDate();
const birthDateString = birthDate.toDateString();
You can also check out Moment.js, it helps a lot when dealing with Dates and displaying them.
This boils down to : how do I convert a unix timestamp to a human readable date?
There are several ways to do this but one of the easiest is to use
var readableData = new Date(doc.data().myUnixTimestamp).toLocaleDateString("en-US");
There are options for all locales. See MDN's Date.prototype.toLocaleDateString.

Reading data from influxDB in a nodeJS application?

can you help me with getting data out of an influx DB instance inside a nodeJS application?
I have tried https://github.com/node-influx/node-influx and https://github.com/vicanso/influxdb-nodejs with only little success.
const Influx = require('influxdb-nodejs');
//Database connection Influx
const client = new Influx('http://redacted/db');
exports.connectInflux = function () {
var date = new Date();
var timeTo = date.toISOString()
date.setDate(date.getDate() - 4)
var timeFrom = date.toISOString()
var reader = client.query('impulse')
.where('location', 'SA08')
.where('time', timeFrom, '>')
.where('time', timeTo, '<')
.then(function (data) {
console.info(data.results[0].series[0].values)
return data.results[0].series[0].values
})
.catch(console.error);
// I get the measurements
client.showMeasurements()
.then(console.info)
.catch(console.error)
}
With this code snippet, at least I can get the data in the console. But when trying to work with it, I only get an empty array. Can you spot any mistake here?
I am thankful for every hint!
Thanks!
Remember that by default, time must be in nanoseconds. You are using milliseconds.

Bulk-delete items from a firebase database in node.js

I'm trying to delete all nodes with a date greater than '2017-04-05' with a bulk operation with a firebase function. Can you spot what I'm doing wrong here?
The 2 nodes that should get deleted are the ones in red:
Here's the code that is failing - can you see what's wrong? Also, I'm concerned about the performance of this (I'll only run it once in a while though). If there are millions of games in the list, should that concern me if I only run this once a day?
exports.remove = functions.https.onRequest((req, res) => {
const deleteBeforeDate = req.query.deleteBeforeDate;
var ref = admin.database().ref('games');
var keysToDelete = {};
for (var game in this.games) {
var date = items[i]['.date'];
if(date.value > '2017-04-05'){
keysToDelete[game.key] = null;
}
}
this.ref.update(keysToDelete);
});
Thank you very much,
Mike
To determine the keys to delete, you'll need to attach a listener. Since that is needed, you might as well create a query that selects the correct children and deletes only those:
var ref = admin.database().ref('games');
var deleteAfterDate = ref.orderByChild('date').startAt('2017-04-05');
deleteAfterDate.once('value').then(function(snapshot) {
var updates = {};
snapshot.forEach(function(child) {
updates[child.key] = null;
});
ref.update(updates);
});

How to process ISO date sting in the MongoDB mapReduce function in Node.js

I'm using the Date function in the mapReduce function in the Node.js application. In the map function below, I convert the ISO date string to the Date object first. Then get the year of the date, which will be used as the key. The expected result is the _id in the output collection is "2013". But in fact, the _id is NaN (The type is Double).
It seems that the Date function used inside the mapReduce function is different from normal JS Date function.
How can I use the normal JS Date function inside the map function below?
If it is impossible, how to process the ISO date string inside the map function?
.
var mongodb = require('mongodb');
var map = function() {
var date = new Date("2013-03-19T08:27:58.001Z"); // Convert ISO date string to Date object
var year = date.getFullYear(); // Get the year of the date.
emit(year, this);
};
var reduce = function(key, values) {
if (values.length) {
return values[0];
}
};
/**Connect to MongoDB
*/
var server = new mongodb.Server(dbIP, dbPort, {});
var db = new mongodb.Db(dbName, server, {safe:true});
db.open(function (err, client) {
if( err ) {
console.log('DB: Failed to connect the database');
}
else {
console.log('DB: Database is connected');
db.collection(collectionName).mapReduce(
map,
reduce,
{
out: 'map_reduce_collection'
}
, function (err, collection, stats){
if( err ) {
console.log('Map reduce: Fail.');
}
else {
console.log('Map reduce: Success.');
}
db.close();
});
}
});
=======EDIT: Add the solution=========
ISODate solves my issue. The code below works for me.
// The map and reduce functions are serialized by the driver and run in the MongoDB server.
// The functions used in them should be supported by the mongo shell.
// A tip is checking if a function is supported by map-reduce function by execuing it in the mongo shell.
// For example, the Date function is different from the one supported by Node.js.
// In Node.js, the var date = new Date("2013-03-19T08:27:58.001Z"); works. But it doesn't work in mongo shell.
// So it can't be used in the map function.
var map = function() {
var date = new ISODate("2013-03-19T08:27:58.001Z");
var year = date.getFullYear();
emit(year, this);
};
Thanks,
Jeffrey
Post the answer here.
ISODate solves my issue. The code below works for me.
// The map and reduce functions are serialized by the driver and run in the MongoDB server.
// The functions used in them should be supported by the mongo shell.
// A tip is checking if a function is supported by map-reduce function by execuing it in the mongo shell.
// For example, the Date function is different from the one supported by Node.js.
// In Node.js, the var date = new Date("2013-03-19T08:27:58.001Z"); works. But it doesn't work in mongo shell.
// So it can't be used in the map function.
var map = function() {
var date = new ISODate("2013-03-19T08:27:58.001Z");
var year = date.getFullYear();
emit(year, this);
};

In node.js, how to use node.js and mongodb to store data in multiple levels

I met a wired problem, that when i use mongodb to store data, some data is missing, which I think it is because of its asynchronous feature
So for this list the timetable, I would use re
/* Here is the a application, in which by using a train_uid and today,
*/
var today = new Date();
var day = today.getDay();
scheduleModel.findByTrainAndTime(train_uid,today,function(err, doc){
var a = new Object();
if(err){}
else{
if(doc != null)
{
//mongodb database can give me some data about the train_id ,uid
a.train_uid = doc.train_uid;
a.train_id = train_id;
and most importantly a train schedule time table, the train schedule time table is a list ( doc.time_schedule )of json objects like arrival, departure and tiploc. However, I need to change the tiploc to sanox number, which referenceModel can help find sanox by providing tiploc number.
//doc.time_schedule
// here is to add a array
so I use async, for each item in the list, I use referenceModel to query sanox and construct a array - a.timeline to store each b, at last when async each operation is finished, trainModel is to store a object with an array of sanox object. However when it comes to the mongodb database, only the array of sanox objects are empty, I guess it is because of asynchronous operation, but since I used async , why it doesn't work
a.train_uid = doc.train_uid; //works
a.train_id = train_id; works
a.timeline = [] // doesn't work
a.timeline = new Array();
var b ;
async.forEachSeries(doc.time_schedule,
function(item,callback){
referenceModel.findStanoxByTicloc(item.tiploc_code,function(err,sanox){
try{
b = new Object();
b.sanox = sanox;
a.time.push(b);
}catch(err2){
}
});
callback();
},
function(err){
trainModel.createNewTrain(a,function(){});
}
}
});
You're calling callback after you fire off the asynchronous find, but before it actually comes back. You need to wait until after you've gotten the data to do that. The following should work better:
async.forEachSeries(doc.time_schedule,
function(item,callback){
referenceModel.findStanoxByTicloc(item.tiploc_code,function(err,sanox){
try{
b = new Object();
b.sanox = sanox;
a.time.push(b);
}catch(err2){
}
callback();
});
},
function(err){
trainModel.createNewTrain(a,function(){});
}

Resources