FieldValue undefined when using functions and Firestore - javascript

I have the following function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const FieldValue = require('firebase-admin').FieldValue;
module.exports = functions.firestore
.document('students/{studentId}')
.onDelete(event => {
const student = event.data.previous.data();
const { id, semester } = student;
const classId = student.class;
const deleteObj = {};
deleteObj[id] = FieldValue.delete(); //Line 12, this is where the error orccurs
return admin
.firestore()
.collection('semesters')
.doc(semester)
.collection('students')
.doc(classId)
.update(deleteObj);
});
Every time i run it I get the following error:
TypeError: Cannot read property 'delete' of undefined
at module.exports.functions.firestore.document.onDelete.event (/user_code/deleteStudent.js:12:37)
Looking at the docs I cant really see what I am doing wrong?
// Get the `FieldValue` object
var FieldValue = require("firebase-admin").FieldValue;
// Create a document reference
var cityRef = db.collection('cities').doc('BJ');
// Remove the 'capital' field from the document
var removeCapital = cityRef.update({
capital: FieldValue.delete()
});
Update
So, using the web equivalent seems to work: admin.firestore.FieldValue.delete(). But that seems like a bug since i'm in a nodejs environment? Can any Firebaser confirm or deny wether that is the case or not? I'd gladly file a bug report.

Turns out it was a mistake in the documentation, the correct import should have been const FieldValue = require('firebase-admin').firestore.FieldValue;
Update
It should be said that Firebase responded within hours and are correcting the docs asap.

It worked!
Require firebase-admin
const admin = require('firebase-admin')
Add this constant
const fieldValue = admin.firestore.FieldValue;
Now use
fieldValue.delete()
For more reference : otcollect.com/post

Here you can find the solution on github.
Using typescript with
"firebase-admin": "^11.0.0"
"firebase-functions": "^3.22.0"
you have to use
import { FieldValue } from 'firebase-admin/firestore'
Same for TimeStamp

Related

Flutter Firebase Functions Error: Database not defined

I've created a delete oldFiles function for my Database that deletes nodes from my chat messages. I've used the example function provided by Firebase and updated it to fit my use. My database structure is databaseName/messages/{pushId} and I've added const functions = require('firebase-functions') and const admin = require('firebase-admin') and admin.initializeApp(). Here is what I have...
exports.deleteOldItems = functions.database.ref('messages/{pushId}').onWrite(async (change) => {
const ref = change.after.ref.parent; // reference to the parent
const now = Date.now();
const cutoff = (DateTime.now().millisecondsSinceEpoch - CUT_OFF_TIME);
const oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
const snapshot = await oldItemsQuery.once('value');
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
updates[child.key] = null;
});
// execute all updates in one go and return the result to end the function
return ref.update(updates);
});
When I review my Function logs, I'm getting the following errors...
ReferenceError: DateTime is not defined
at exports.deleteOldItems.functions.database.ref.onWrite (/srv/index.js:17:18)
at cloudFunction (/srv/node_modules/firebase-functions/lib/cloud-functions.js:131:23)
at /worker/worker.js:825:24
at
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
And my Functions are finishing with status: error. Any ideas to what may be going on?
DateTime isn't a valid JavaScript object or identifier. If you want to work with dates and times, you will need to work with Date, as you are in the line just above where you have DateTime. You should probably review the JavaScript documentation for Date to learn how it works.

Cloud Function error "Cannot read property 'data' of undefined"

I recently started playing with cloud functions and I am getting this error:
> TypeError: Cannot read property 'data' of undefined
> at exports.createPost.functions.firestore.document.onCreate (/srv/index.js:15:37)
> at cloudFunction (/srv/node_modules/firebase-functions/lib/cloud-functions.js:131:23)
> at /worker/worker.js:825:24
> at <anonymous>
> at process._tickDomainCallback (internal/process/next_tick.js:229:7)
and this is my code
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const algoliasearch = require('algoliasearch');
const ALGOLIA_APP_ID = "";
const ALGOLIA_ADMIN_KEY = "";
const ALGOLIA_INDEX_NAME = "Posts";
admin.initializeApp(functions.config().firebase);
//const firestore = admin.firestore;
exports.createPost = functions.firestore
.document('User/{UserId}/Posts/{PostsID}')
.onCreate( async (snap, context) => {
const newValue = snap.after.data();
newValue.objectID = snap.after.id;
var client = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_ADMIN_KEY);
var index = client.initIndex(ALGOLIA_INDEX_NAME);
index.saveObject(newValue);
});
The onCreate function triggers at the right time and the problem is just the error. I have done my research and couldn't figure it out. I hope I can get some help.
Thanks in advance :).
onCreate functions receive a DocumentSnapshot type argument as its first parameter. It looks like your function is not actually expecting that. Since you're trying to use a property called after, it looks like your code is expecting a Change type argument, which will never be the case for onCreate events. Change type objects are delivered to onUpdate or onWrite events only so you can detect the before and after states of a document.
If you want the data from a newly created document in an onCreate type trigger, you should code like this:
exports.createPost = functions.firestore
.document('User/{UserId}/Posts/{PostsID}')
.onCreate( async (snap, context) => {
const newValue = snap.data();
// use the document properties of newValue here

Increment Realtime Database count on new user with Firebase Cloud Function

* UPDATED: THIS WORKS. SEE ANSWER BELOW *
I'm trying to write a Firebase Cloud Function that increments a Realtime Database /userCount value whenever a new user is created.
I've tried the following, but am getting "TypeError: userCountRef.transaction is not a function" in incrementCountOnNewUser.
Transactions are working for my other function incrementCountOnOpen when the value of garage is set to true, but the ref is derived from the after event object.
Any suggestions on how to do this?
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
// const userCountRef = functions.database.ref("/userCount"); // does NOT work
const userCountRef = admin.database().ref('/userCount'); // THIS WORKS!
exports.incrementCountOnNewUser = functions.auth.user().onCreate((user) => {
return userCountRef.transaction(count => count + 1);
});
exports.incrementCountOnOpen = functions.database.ref("/garage").onUpdate(({after}) => {
const countRef = after.ref.parent.child('count');
const newValue = after.val();
return newValue
? countRef.transaction(count => count + 1)
: null;
});
It turns out that the code above works! I had switched from the commented out code (which does NOT work). I guess it didn't wait long enough for it propagate after I published, because I see it working now!
Sorry for the confusion.

How do I get the server timestamp in Cloud Functions for Firebase with Firestore?

How can we get a server timestamp, without using the realtime database
but using instead Firestore ?
import * as functions from 'firebase-functions'
import { Firestore } from '#google-cloud/firestore'
const db = new Firestore()
export let testIfMatch = functions.firestore
.document('users/{userId}/invites/{invitedUid}')
.onCreate(event => {
let invite = <any>event.data.data()
if (invite.accepted == true) {
return db.collection('matches').add({
friends: [userId, invitedUid],
timestamp: doc.readTime // <--- not exactly the actual time
})
}
Use server timestamp with Firestore is little different:
// Get the `FieldValue` object
var FieldValue = require("firebase-admin").FieldValue;
// Create a document reference
var docRef = db.collection('objects').doc('some-id');
// Update the timestamp field with the value from the server
var updateTimestamp = docRef.update({
timestamp: FieldValue.serverTimestamp()
});
if it's not working you can edit the var FieldValue = require("firebase-admin").FieldValue; with var FieldValue = require("firebase-admin").firestore.FieldValue;
Here's a slightly more concise way of doing it:
import * as admin from "firebase-admin"
const timestamp = admin.firestore.FieldValue.serverTimestamp();
Here's my way of doing it. It doesn't require adding '#google-cloud/firestore' as a dependency to your project, and eliminates adding lots of admin.firestore.xxx to your code.
import * as admin from "firebase-admin";
import FieldValue = admin.firestore.FieldValue;
// import anything else you want to alias
someRef.set({timestamp: FieldValue.serverTimestamp()});
If you are using Firestore, you can use such below code snippet.
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore()
val ts = db.FieldValue.serverTimestamp()
If you are using "firebase-admin": "10.0.0"
You can use the below snippet.
const {FieldValue} = require('firebase-admin/firestore');
const timestamp = FieldValue.serverTimestamp();

Cloud Function for Firebase Type Error - Cannot Read Property

I'm trying to write a Cloud Function that creates a record whenever someone uses our legacy app to create a record (we have changed the Firebase backend architecture and want to slowly migrate users). However, I'm getting the following error in my logs:
TypeError: Cannot read property 'update' of undefined
at exports.makeNewComment.functions.database.ref.onWrite.event (/user_code/index.js:14:92)
at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:35:20
at process._tickDomainCallback (internal/process/next_tick.js:129:7)
Here is the script in question:
//required modules
var functions = require('firebase-functions');
const admin = require('firebase-admin');
// Listens for new comments added to /comments/ and adds it to /post-comments/
exports.makeNewComment = functions.database.ref('comments/{commentId}').onWrite(event => {
// Grab the current value of what was written to the Realtime Database.
const commentId = event.params.commentId;
const comment = event.data.val();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
//return event.data.ref.parent.child('post-comments').set(comment);
return functions.database.ref('post-comments/' + comment['postID'] + '/' + commentId).update(comment).then(url => {
return functions.database.ref('user-comments/' + comment['postedBy'] + '/' + commentId).update(comment);
});
});
//initialize
admin.initializeApp(functions.config().firebase);
Thanks!
You can't use functions.database.ref() in the middle of a function to get a ref to somewhere in your database. That's only for defining a new Cloud Function.
If you want a ref to somewhere in your database, you can use event.data.ref or event.data.adminRef to get a ref to the location where the event triggered. You could then use the root property of that to rebuild a new ref to somewhere else in the database. Or you can use your admin object to build a new ref.
It might be helpful to look at some sample code to get a sense of how things work.
Based on Doug's answer, you can replace functions.database.ref with event.data.ref.root.
var functions = require('firebase-functions');
const admin = require('firebase-admin');
exports.makeNewComment = functions.database.ref('comments/{commentId}').onWrite(event => {
const commentId = event.params.commentId;
const comment = event.data.val();
return event.data.ref.root.child('post-comments/' + comment['postID'] + '/' + commentId).update(comment).then(url => {
return event.data.ref.root.child('user-comments/' + comment['postedBy'] + '/' + commentId).update(comment);
});
});
admin.initializeApp(functions.config().firebase);

Categories

Resources