I want to rewrite all documents in a collection with firebase functions - node.js

I am developing an app in flutter. I would like to rewrite the value of "life" field of all documents in the "users" collection of the Firestore to "10(int)" at 00:00 Tokyo time.
I managed to write the code anyway, but I am completely clueless about JavaScript and Functions, so it doesn't work.  I would like to know how to correct it. This is my code.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
process.env.TZ = "Asia/Tokyo";
export const checkTimezone = functions.region('asia-northeast1').https.onRequest(async (req, res) => {
console.info(process.env.TZ)
});
exports.timer = functions.pubsub.schedule('00***').onRun((context) => {
functions.logger.info("timer1 start", {structuredData: true});
admin.firestore().collection("users").get().then(function(querySnapshot){
querySnapshot.forEach(function(doc){
doc.ref.update({
life:10
});
});
})
});

The default timezone for Cloud Functions is America/Los_Angeles. You can set the timezone to Asia/Tokyo so the function will run at every midnight in Japan. Also, you must return a promise from the function to terminate it once the updates have been completed. Try refactoring to code as shown below:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
exports.timer = functions.pubsub
.schedule("0 0 * * *")
.timeZone("Asia/Tokyo")
.onRun((context) => {
functions.logger.info("timer1 start", {structuredData: true});
const usersRef = db.collection("users");
return usersRef.get().then((snapshot) => {
const promises = [];
snapshot.forEach((doc, i) => {
promises.push(doc.ref.update({ life: 10 }));
});
return Promise.all(promises);
});
});

Related

how to change Firestore document data using Google Cloud Functions in node.js

I am trying to write a google cloud function that will check all documents under a collection in every minute and if a boolean parameter after 15 minutes later still false, it will change another document parameter.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.scheduledFunctionAppointment =
functions.pubsub.schedule('every 1 minutes').onRun((context) => {
const timestamp = FieldValue.serverTimestamp()
return getReceivers(mUserGroup).then((snapshot) => {
snapshot.forEach(doc => {
const mAppointmentObj = doc.data();
const mAppointmentCreationDate = mAppointmentObj.appointmentCreationDate;
const mAppointmentDate = mAppointmentObj.appointmentDate;
const mChaplainId = mAppointmentObj.chaplainId;
const mAppointmentId = mAppointmentObj.appointmentId;
const mIsAppointmentPaymentDone = mAppointmentObj.isAppointmentPaymentDone;
if (timestamp-mAppointmentCreationDate >= 900000){
if(mIsAppointmentPaymentDone === false){
admin.firestore().collection('chaplains').doc(mChaplainId).collection('chaplainTimes').doc('availableTimes').update({
mAppointmentId: {
isBooked: false
}
});
}
}
});
});
})
async function getTaskAppointments() {
const snapshot = await admin.firestore().collection('appointment_temporary').get();
return snapshot;
}
the code should check the appointment_temporary collection in every 1 minute. In every check, it will take the server time and appointment creation date. If after 15 minutes later, isAppointmentPaymentDone still false, it will make isBooked false that under availableTimes map data.
I wrote a function but it gives error. I am a mobile developer. I am not familiar with the node.js. Thank you very much for the help in advance.

My onCreate funciton in Functions of firebase is not creating my desired collection in the cloud database

I just typed a code in my index.js file of functions (firebase CLI).According to my code there must be a timeline collection created in cloud database of firebase.Function is healthy and there are no errors it gets deployed and even in the logs everything works fine. But still timeline collection is not created in the cloud databaese when I follow a user in my app.
this is my code:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.onCreateFollower = functions.firestore
.document("/followers/{userId}/userFollowers/{followerId}")
.onCreate(async (snapshot, context) => {
console.log("Follower Created", snapshot.id);
const userId = context.params.userId;
const followerId = context.params.followerId;
// 1) Create followed users posts ref
const followedUserPostsRef = admin
.firestore()
.collection("posts")
.doc(userId)
.collection("userPosts");
// 2) Create following user's timeline ref
const timelinePostsRef = admin
.firestore()
.collection("timeline")
.doc(followerId)
.collection("timelinePosts");
// 3) Get followed users posts
const querySnapshot = await followedUserPostsRef.get();
// 4) Add each user post to following user's timeline
querySnapshot.forEach(doc => {
if (doc.exists) {
const postId = doc.id;
const postData = doc.data();
return timelinePostsRef.doc(postId).set(postData);
}
});
});
Since you want to execute a variable number of asynchronous calls in parallel, you should use Promise.all(), in order to wait that all these different asynchronous calls are completed before indicating to the CF platform that it can cleanup the CF. See https://firebase.google.com/docs/functions/terminate-functions for more details.
exports.onCreateFollower = functions.firestore
.document("/followers/{userId}/userFollowers/{followerId}")
.onCreate(async (snapshot, context) => {
const userId = context.params.userId;
const followerId = context.params.followerId;
// ...
// 3) Get followed users posts
const querySnapshot = await followedUserPostsRef.get();
// 4) Add each user post to following user's timeline
const promises = [];
querySnapshot.forEach(doc => {
//query results contain only existing documents, the exists property will always be true and data() will never return 'undefined'.
const postId = doc.id;
const postData = doc.data();
promises.push(timelinePostsRef.doc(postId).set(postData));
});
return Promise.all(promises);
});

Express JS: Send Databse as Variable / Parameter while requiring a module

Say I have the following code
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const serviceAccount = require("./permissions.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://blah-blah-blah.firebaseio.com"
});
const db = admin.firestore();
app.use("/auth", require("./auth"));
Now the problem is that I have to use the cloud firestore databse functionality, which is curently stored in the variable db, in my auth.js file as well, without using admin.initializeApp a second time. Is there any way to acomplish that, like importing/exporting the db variable etc.
This is where I am using it in auth.js:
const express = require("express");
const auth = express.Router();
db.collection("data")
.doc("sample")
.get()
.then(
document => {
if (document.exists) {
return done(null, {
id: user.id,
name: user.name,
email: user.email
});
} else {
//create document
}
},
err => {
//handle error
}
);
Of course, right now db will be undefined, which is the problem I need to tackle
Since version 1.0.0 of the Firebase SDK for Cloud Functions you have to initialize with admin.initializeApp();, see the doc here.
Then, to interact with Firestore, you just need to use the Admin SDK, for example as follows:
admin.firestore().collection('....').get();
So, if I understand correctly your question, the following changes should do the trick:
index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
//const db = admin.firestore(); not sure you need that here, it depends if you interact (or not) with Firestore in index.js
app.use("/auth", require("./auth"));
auth.js
const admin = require("firebase-admin");
const db = admin.firestore();
//....
db.collection("data")
.doc("sample")
.get()
.then(
document => {
if (document.exists) {
return done(null, {
id: user.id,
name: user.name,
email: user.email
});
} else {
//create document
}
},
err => {
//handle error
}
);
//....

Error upon Cloud Function for Firebase deployment

I've been trying to deploy a Cloud Function to my Firebase project.
It's my first time doing so, also my first time programming with JavaScript.
Here's my code in Node.JS:
'use strict'
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const firebaseTriggers = functions.region('europe-west1').firestore;
const db = admin.firestore();
exports.postNotification = firebaseTriggers
.document('/post notifications/{notificatioId}').onWrite((snap, context) => {
const notifcationRecieverId = snap.data().mReciever;
const payload = {
data: {
notification_type: 'POST',
title: snap.data().mTitle,
body: snap.data().mDescription,
sender_id: snap.data().mSender,
reciever_id: snap.data().mReciever,
notification_id: context.params.notificatioId
}
};
return db.collection('dog owners')
.document(notifcationRecieverId)
.get()
.then(recieverDoc => {
console.log('Retrieving FCM tokens');
const tokens = recieverDoc.data().mTokens;
console.log('Sending notification payload');
return admin.message().sendToDevice(tokens, payload);
});
});
Upong deployment, I'm getting the following error:
Can someone help me understand why?
Firstly you have got space in your colleciton name. This is bad convetion.
post notifications => postNotifications

Problem with the set() function from GeoFirestore

I want to use the set(...) function, but Firebase-Log says that this function is not available.
The Firebase-Cloud-Function Log:
"TypeError: GeoPostLocations.set is not a function
at database.collection.doc.collection.doc.set.then.result"
const functions = require('firebase-functions');
const functions = require('firebase-functions');
var admin = require('firebase-admin');
var serviceAccount = require('./serviceAccountKey.json');
var GeoFirestore = require('geofirestore').GeoFirestore;
const database = admin.firestore();
const geofirestore = new GeoFirestore(database);
const GeoPostLocations = geofirestore.collection('PostLocations');
In my function, I execute the following code:
return GeoPostLocations.set("DummyIDForTest", [50.312312312, 5.4302434234]]).then(result => {
console.log(result);
return 0;
}).catch(error => {
console.log(error);
return 1;
});
So it looks like you've been doing a bit of your code in the syntax of version 2 of geofirestore, but we're now on v3 and things should look more like firestore, so what does that mean for you?
Firstly, set isn't a function available to collections, but it is available to documents, so you'll wanna do this:
return GeoPostLocations.doc('DummyIDForTest').set({
coordinates: new firebase.firestore.GeoPoint(50.312312312, 5.4302434234)
}).then(result => {
console.log(result);
return 0;
}).catch(error => {
console.log(error);
return 1;
});
Please note that you have to set an object, not coordinates in an array (this isn't geofire). I've included a link to the relevant docs.

Resources