Getting a Cloud Firestore document reference from a documentSnapshot - javascript

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

Related

Converting JSON to Array with Cloud Functions

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.

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.

Genrate doc id in firestore v9 before the doc is created

In firestore v8 (web sdk) I was doing it like below:
firestore.ref().collection("genId").doc().id
But I can't figure out the correct syntax for v9 as collection doesn't have doc() method anymore.
Any suggestions are much appreciated
From the Firebase documentation on adding a document:
In some cases, it can be useful to create a document reference with an auto-generated ID, then use the reference later. For this use case, you can call doc():
import { collection, doc, setDoc } from "firebase/firestore";
// Add a new document with a generated id
const newCityRef = doc(collection(db, "cities"));
// later...
await setDoc(newCityRef, data);
Instead of writing to the ref as the sample does, you can also get the ID from the document ref with:
console.log(newCityRef.id);
You can call collection to get a CollectionReference Object and use this to call doc.
Collection: https://firebase.google.com/docs/reference/js/firestore_.md#collection
Doc: https://firebase.google.com/docs/reference/js/firestore_.md#doc_2
const ref = collection(firestore, "genId")
const id = doc(collection)
As per the API reference:
If no path is specified, an automatically-generated unique ID will be
used for the returned DocumentReference.

How to save a Mongo document's own _id in a nested field?

This Meteor server code tries to copy the newly created property _id into a sub document but failed to do so.
How can it be done?
edit:
The code uses matb33:collection-hooks.
MyCollection.after.insert(function(userId, doc) {
if (doc.element === 'myString') {
doc.values[0]._id = doc._id;
}
});
Mutating the doc in the after hooks of matb33:collection-hooks will not cause additional queries to be run. You will need to explicitly update the document if you wish to do so.
However, in this particular case, if you really need the duplicate _id in the document, you could generate an _id and specify it when inserting the document.
You can probably use MyCollection._makeNewID() method, as this API has not changed for a few years and it is what the Mongo package uses internally.
const _id = MyCollection._makeNewID();
const doc = {
_id,
values: [
{
_id,
...
}, {
...
}
]
};
MyCollection.insert(doc);

Categories