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.
Related
I posted a question earlier about how to query for a specific value inside an array. I was told that there was a similar question already asked. I have looked at the solution for that question however i am getting an error. This is my code currently to check to see if the field mal_id inside the favourites array contains an id passed by me.
const docRef = collection(db, 'users')
const q = query(docRef, where('favourites', 'array-contains', {mal_id: id}))
I then attached an onSnapshot method to see if the data exists which is like this
onSnapshot(q, (snapshot) => {
if(snapshot.data()){
console.log(true)
}
else{
console.log(false)
}
})
But i get an error saying snapshot.data is not a function. idk if you are not supposed to use an onSnapshot method on this kind of query or my code is wrong. I have attached a picture of my database structure. Thanks.
*Edit
So, i have changed my data structure. Now i am creating a new field called animeID and then storing the id into it. I then do the array contains onto that but the snapshot still gives me the same error. Here is the updated code along with a new picture of my database structure.
const docRef = collection(db, 'users')
const q = query(docRef, where('animeID', 'array-contains', `mal_id: ${id}`))
onSnapshot(q, (snapshot) => {
if(snapshot.data()){
console.log(true)
}
else{
console.log(false)
}
})
Updated firestore structure
As Doug commented, Firestore's array-contains operator checks for equivalence between the value you supply and an entire array item. It can't find a subset of an item.
The common workaround is to add an additional field to your document with just the mal_id values you want query on. So something like:
Favourites_mal_ids: [21]
And then you can perform an array-contains on that field.
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.
I'm using Ionic 4 and have just integrated with AngularFire. Collections and documents work well, however I cannot get the collectionGroup function to work - it always gives an error that the function does not exist.
Relevant code is :
this.user = this.firestore.collection('profile').doc(tok.uid);
async StoreRecipe(recipe_name,meal) {
var ua = await this.read_foods_meal(meal+1)
console.log(meal);
ua.subscribe( foods => { console.log(foods);
foods.forEach(food => { this.user.collection('recipe').doc(recipe_name).collection('foods').add(food);} )
});
}
async read_recipes() {
var ua = await this.user.collectionGroup('recipe');
return(ua);
}
I have updated all modules with 'Fire' in the name to the latest version :
#angular/fire
#ionic-native/firebase-x
angularfire
firebase
firebase-admin
But the error still appears. Also, If I try to query the recipe collection using the .collection() function it just returns a null result .. even though there are documents under the 'recipe'collection
You user object is an instance of the firebase.firestore.DocumentReference class, and it does not have a collectionGroup method. Check the documetation here.
If you want to run a query across various collections, these should have the same name, and you can use the firebase.firestore().collectionGroup() method. You can find how to configure it in this link.
If you just want to get all the documents inside your recipe collection, you can make use of the CollectionReference.get() method (documentation).
The goal is to update a Firebase document.
The document ID is unknown at the time of updating. What is known is a property that acts as unique key on the document (email address in the case below).
Based on the official documentation and this answer, the code below works as a method for updating an array within the document.
This feels clunky, though.
Are there more direct methods for retrieving a reference to a single document and updating its fields?
// Set query.
let query = firebase.firestore().collection('users').where('emailAddress', '==', 'test#test.com');
// Run query.
try {
const querySnapshot = await query.get();
return querySnapshot.docs[0].ref.update({
designs: firebase.firestore.FieldValue.arrayUnion('foobar')
})
} catch(e) {
console.log('Error getting user: ', e);
}
No, what you're doing is the best you can do. If you don't know the ID, you have to query to find it. Firestore has no equivalent of a SQL "update where" command.
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(...)
})