Converting JSON to Array with Cloud Functions - javascript

When I use this function I get the following result from my realtime database. It looks like a json object.
How can I turn that to an array or retrieve the string userName? snapshot.userName is not working.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.Push = functions.database.ref('/placeID/{pushId}/')
.onCreate((snapshot, context) => {
console.log(snapshot)
})

A Realtime Database DataSnapshot object is a container that contains your data. To get the data it contains, you need to retrieve its value using the val() method:
console.log(snapshot.val());
To get the userName from your data, you can use either:
console.log(snapshot.val().userName)
// note: if "userName" is missing, this will log `undefined`
or
// more useful with large snapshots
console.log(snapshot.child("userName").val())
// note: if "userName" is missing, this will log `null`
See following link for more info about the DataSnapshot object and available methods/properties:
https://firebase.google.com/docs/reference/functions/providers_database.datasnapshot
Added note: The DataSnapshot class overrides the toJSON() method, this is why when you log it, you saw the data it contained rather than the DataSnapshot's own methods/properties.

snapshot is a reference to a Firestore document. In order to get the data contained in a document doc you need to call doc.data(). So in your case it would be doc.data().userName.
See the documentation for some examples.

Related

Firebase document reference field gets set as string field type instead of reference field type

Problem: User reference field set as string field type instead of reference field type.
Context: When a new user is created, the below function should create a new document in a collection called "Workout Cycles" in Firebase. The new user document is created and the Workout Cycles document is created, but the "user" field (which is the aforementioned user reference) is populated as a string and not as a reference. See example of newly created Workout Cycles document with user field set as string here: Example of document with "user" field set as string instead of reference
How the user field is currently set:
I am using const userDocReference = snap.id; to capture the UID of the user that was created and storing it in userDocReference. Once stored, I use the set() command to create the new Workout Cycles document in Firebase. I am currently setting the user field with user: userDocReference, within the set() command to assign the .
Here is the function code:
import functions = require("firebase-functions");
require("firebase-functions");
import admin = require("firebase-admin");
require("firebase-admin");
admin.initializeApp();
"use strict";
functions.logger.debug("debug level in web console and gcp");
functions.logger.log("info level in web console and gcp");
functions.logger.info("info level in web console and gcp");
functions.logger.error("error level in web console and gcp");
exports.createWorkoutCycle = functions.firestore
.document("users/{userId}")
.onCreate((snap, context) => {
// Get an object representing the document
// e.g. {'name': 'Marie', 'age': 66}
const date = new Date();
const dateString = date.toString();
const userDocReference = snap.id;
return admin.firestore().collection("WorkoutCycles").doc().set({
name: "New Workout Cycle",
createTimestamp: dateString,
user: userDocReference,
});
});
snap.id is indeed a string with the ID of the users document and not a reference, so this code is behaving correctly as you've described.
If you instead want a reference to the users document, it might be helpful to know that snap is a DocumentSnapshot object. It has a ref property which is a DocumentReference.
const userDocReference = snap.ref;
It's also conventional not to store dates as strings and instead use a Firestore timestamp, which makes it possible to sort the documents chronologically. Simply use a JavaScript Date object to get that behavior.

Cloud Firestore: Get Value from collection ID if it exists

I want to obtain the value of a collection ID from a collection in cloud firestore if it exists:
export const getSlugs = async () => {
const document = await db
.doc(constDocumentRefs.slugs)
.collection('<collection_id>')
return ;
};
but this returns me collection reference, I can check if its empty by calling: document.get().empty method but not sure how do I get the value of collection, in case it is not empty.
My collection looks like this:
{
key1:1
key2:2
}
I want to keep it like return the actual value if collection exists otherwise return -1. Someone please help!
I can see two possible ways:
From the front-end:
As Dharmaraj mentioned in his comment, you need to fetch document(s) in the collection to see if the querySnapshot is empty or not. If the snapshot is empty, the collection does not exist. You can limit the query to only one document to minimize cost. For that you'll use the limit() method. And for checking if the QuerySnapshot contains a doc use the size property.
From a back-end:
The Admin SDKs offer a specific method to list collections, for example listCollections() for the Node.js Admin SDK (and listCollections() method of a DocumentReference for listing sub-collections). You can implement that in a Cloud Function and call it from your front-end: I wrote an article on this approach.

Firebase: Trouble getting field value

Given the following data struct in firebase, I wish to retrieve the field in just standard JS. I have tried many methods of getting it, but for some reason, I cannot. I have tried .get(), forEach(), I have tried getting a snapshop, but it won't work.
At the start of my JS file I do:
const auth = firebase.auth();
const db = firebase.firestore();
let totalGroups;
db.collection('totalGroups').doc('totalGroups').get().then(function(querySnapshot) {
querySnapshot.docs.forEach(function(doc) {
if (doc.data().totalGroups != null) {
totalGroups = doc.data().totalGroups console.log("here is total groups" + totalGroups)
//Total Groups is undefined out here but defined in fuction
}
})
})
and normally I am able to get .get() just fine. I am looking for the most simple method of getting this value. thanks.
First, you are using get() on a DocumentReference which returns a DocumentSnapshot containing data of that single document only and has no docs property on it. Try refactoring the code as shown below:
db.collection('totalGroups').doc('totalGroups').get().then(function(snapshot) {
const docData = snapshot.data();
console.log(docData)
})
Also do note that if you were using get() on a CollectionReference, then it would have returned a QuerySnapshot where the existing code works fine.

Is there a way to update a collectionGroup in cloud function

I'm building a chat app. When a user makes an update on their local profile I'd like to use cloud functions to make that update across a collectionGroup.
I'm successfully listening to the update in cloud functions and retrieving a list of collectionGroups with the following:
const collectionGroupNameref = await db.collectionGroup('collectionGroupName').where('userId', '==', data.uid).get();
collectionGroupNameref.forEach(async (val: any) => {
const connectionsRef = await db.collection('collectionGroupName').doc(val.id).get();
});
But now I need to update a field within that collectionGroup and that's where I'm running into issues.
The collectionGroup is stored in 2 locations:
users{id}collectionGroupName{id}
groups{id}collectionGroupName{id}
Is it possible to update all of the documents in that collectionGroup
Firestore doesn't provide any methods to update an entire collection or collection group like "UPDATE WHERE" in SQL. What you are required to do instead is write each document individually. So, if you've already executed a query for documents in the collection group, can you simply iterate the documents in the result set and update each document as needed. You can use the ref property of DocumentSnapshot to easily update each document, no matter what collection contains it.
const querySnapshot = await db
.collectionGroup('collectionGroupName')
.where('userId', '==', 'data.uid')
.get();
querySnapshot.docs.forEach(snapshot => {
snapshot.ref.update(...)
})

Getting a Cloud Firestore document reference from a documentSnapshot

The issue
I'm trying to retrieve the document reference from a query. My code returns undefined. I can get the path by extracting various parts of documentSnapshot.ref, but this isn't straightforward.
What I'd like to return is a reference which I can then later use to .update the document, without having to specify the collection and use documentSnapshot.id
The documentation for the path property is here
My code
const db = admin.firestore();
return db.collection('myCollection').get().then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
console.log(`documentReference.id = ${documentSnapshot.id}`);
console.log(`documentReference.path = ${documentSnapshot.path}`);
// console.log(`documentReference.ref = ${JSON.stringify(documentSnapshot.ref)}`);
});
});
Output
documentReference.id = Jez7R1GAHiR9nbjS3CQ6
documentReference.path = undefined
documentReference.id = skMmxxUIFXPyVa7Ic7Yp
documentReference.path = undefined
In your code, documentSnapshot is an object of type DocumentSnapshot. It looks like you're assuming that it's an object of type DocumentReference. A the purpose of a reference is to locate a document. The purpose of a snapshot is to receive the contents of a document after it's been queried - they're definitely not the same thing. A DocumentSnapshot doesn't have a path property.
If you want the DocumentReference of a document that was fetched in a DocumentSnapshot, you can use the ref in the snapshot. Then you can get a hold of the ref's path property:
documentSnapshot.ref.path

Categories