I'm working with the following collection and sub-collections in Firestore.
I need to retrieve the list of the documents inside "Schedine", but the following code returns nothing.
const ref1 = await firestore.collection("Schedine").get();
ref1.forEach(doc => {
console.log(doc.id);
});
// expected output: gx8qiytV8Zgs0AJR4swFqTH3T82 , but nothing shown
Instead, if I try to get() the documents inside "in corso", a sub-collection of a document inside "Schedine", it works, with the exact same code:
const ref2 = await firestore.collection("Schedine").doc("gx8qiytV8Zgs0AJR4swFqTH3T822").collection("in corso").get();
ref2.forEach(doc => {
console.log(doc.id);
});
// WORKING
How could I get the list of the documents inside "Schedine"?
If you look carefully, you'll see that the document ID in your screenshot is shown in italics. This means that there's no document gx8qiytV8Zgs0AJR4swFqTH3T822 inside your Schedine collection, and the console just shows that ID so that it can show you the subcollections under it.
Since there's no documents in Schedine, calling get on that collection returns an empty query snapshot. But the path exists, which is why you can access the subcollection once you know the document ID in your second snippet.
There's no API on the collection reference to get such non-existent entities, so the common solution is to create an (empty) document when you also create the subcollection.
Related
Hoi, I would like to check, using React javascript, if a collection in the Firestore already exists, no matter if it's empty or not. I tried:
if (collection(db, ref)) // is always true somehow
Any ideas? Thanks!
You would need to try to fetch from the collection and see if anything is returned:
const snap = await query(collection(db, ref), limit(1));
if (snap.empty) {
// no docs in collection
}
There is no function available in the SDK that can help you can check if a particular collection exists. A collection will start to exist only if it contains at least one document. If a collection doesn't contain any documents, then that collection doesn't exist at all. So that being said, it makes sense to check whether a collection contains or not documents. In code, it should look as simple as:
const snapshot = await query(collection(db, yourRef), limit(1));
if (snapshot.empty) {
//The collection doesn't exist.
}
One thing to mention is that I have used a call to limit(1) because if the collection contains documents, then we limit the results so we can pay only one document read. However, if the collection doesn't exist, there is still one document read that has to be paid. So if the above query yields no resul## Heading ##t, according to the official documentation regarding Firestore pricing, it said that:
Minimum charge for queries
There is a minimum charge of one document read for each query that you perform, even if the query returns no results.
You have to fetch the collection out of the database and check if it has more than 0 documents. Even, if the collection doesn't exist, it will return 0.
const db = firebase.firestore();
db.collection("YOUR COLLECTION NAME").get().then((res) =>{
if(res.size==0){
//Collection does not exist
}else{
//Collection does exist
}
I am having trouble deleting on firestore
here's my delete
var chatId = route.params.number; // +639266825843
var docRef = firestore().collection('ChatRoom').doc(chatId).collection('messages');
docRef.doc(chatId).delete();
but everytime i try to delete nothing happens . There's no error at all .
this is how I set that collection
firestore().collection('ChatRoom')
.doc(id)
.collection('messages')
.add({...myMsg, createdAt:firestore.FieldValue.serverTimestamp()})
If you want to delete all the docs of the messages (sub)collection, you need to query the collection and delete each document, for example by using Promise.all() or by using a batched write (containing only deletions)
var chatId = route.params.number; // +639266825843
var colRef = firestore()
.collection('ChatRoom')
.doc(chatId)
.collection('messages');
colRef.get().then((querySnapshot) => {
Promise.all(querySnapshot.docs.map((d) => d.ref.delete()));
});
The docs property of the QuerySnapshot returns an array of QueryDocumentSnapshots.
In addition, look at how your +639266825843 document is displayed in an italic font: this means, in the console, that this document is only present as "container" of one or more sub-collection(s) but that it is not a "genuine" document. It does not exist, because you never created it, you only created docs in one of its subcollections. More detail here.
I am trying to impelement a delete function in Firestore database and the problem is that when I click delete, it deletes the last document created, not the one that I want to delete.
This is how I get the data from the database:
db.collection("flights").get().then((snapshot) =>{
snapshot.docs.forEach(doc => {
var data = doc.data();
var docID = doc.id;
And this is how I am trying to delete it:
function deleteFlight(docID){
firebase.firestore()
.collection("flights")
.doc(docID)
.delete()
.then(() => console.log("Document deleted")) // Document deleted
.catch((error) => console.error("Error deleting document", error));
}
I want to specify that after I create a new document, the website is refreshed, so I think it loses somehow the document id.
In the comment section you have specified that you are calling the deleteFlight() function from a html button. As you are using forEach() loop after getting the collection of documents and within that populating docID, by the time the html button is clicked the forEach() loop would have been completed and then docID will have the document id of the document which comes last in ascending order because by default the documents are sorted in ascending order of document id as mentioned in this document. In your case I suspect the document id for the recently added document comes last when sorted in ascending order. This is the reason the recently added document is getting deleted.
I am not sure of your use case. But I would suggest you to declare a variable outside of the db.collection() method and implement some logic according to your use case to populate it with the document id which you want to delete. Then use that variable in the deleteFlight() function.
What I need to do:
wanting to check the snapshot to see if anyone else has already taken that username. Seeing if the user input is already in use (the title of the document inside 'users')
I'm trying to get a snapshot of each document title, so a snapshot of the collection info. I know I could do something like mapping each value into an array but the username count is massive and I feel like that might affect performance?
Heres what I have:
const snap = firestore().collection('users').onSnapshot(snapshot => {
console.log(snapshot.data())
})
and this returns saying that snapshot.data() is not a function, if I remove .data() its a large mess of everything, I can post it if you would like.
If you want to check whether a document with a specific name as its ID already exists, you can do:
const snap = firestore().collection('users').doc('Tobias').onSnapshot(snapshot => {
console.log(snapshot.exists)
})
So this logs true is a document named Tobias exists, and false otherwise.
I'm trying to retrieve a single document from a collection. I'm now using the code below that returns a collections of items, but I know that there is only one item. So it ain't that clean.
Setup:
private db: AngularFirestore
private itemSubs: Subscription[] = [];
itemAd= new Subject<Item>();
fetchItemFromDatabase(itemId: string) {
this.itemSubs.push(
this.db.collection('items', id => id.where('itemId', '==', itemId)).valueChanges().subscribe((items: Item[]) => {
this.itemAd.next(items);
}));
}
I tried to do it with this.db.collection('items').doc(itemId).get() , but I'm getting an error on get() that it's not found/supported. I also didn't got autocompletion when trying to call this methode (methode found in the official cloud firestore documents).
I looked at around at some other solutions and then tried it with this.db.collection('items').doc(itemId).ref.get().then(...) , but here I got an empty doc back.
So I'm a bit stuck at the moment and I don't want to use that whole collections logic when I know there is only 1 item in it.
There may be multiple documents with itemId equal to a given value. While you may know that there is only one in your app, the database and API cannot know nor enforce that. For that reason the query you run will always return a query snapshot that potentially contains multiple documents.
this.db.collection('items', id => id.where('itemId', '==', itemId))
If you want to enforce that there is only one document with the given item ID, consider using that item ID as the document name instead of storing it as a field in the document.
There can be only one document with a given name, so that means the ID is guaranteed to be unique. And you can then retrieve that document with:
this.db.collection('items').doc(itemId)