Given a given Firestore path what\'s the easiest and most elegant way to check if that record exists or not short of creating a document observable and subscribing to it?
Taking a look at this question it looks like .exists
can still be used just like with the standard Firebase database. Additionally, you can find some more people talking about this issue on github here
The documentation states
NEW EXAMPLE
const cityRef = db.collection('cities').doc('SF');
const doc = await cityRef.get();
if (!doc.exists) {
console.log('No such document!');
} else {
console.log('Document data:', doc.data());
}
Note: If there is no document at the location referenced by docRef, the resulting document will be empty and calling exists on it will return false.
OLD EXAMPLE
var cityRef = db.collection('cities').doc('SF');
var getDoc = cityRef.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
console.log('Document data:', doc.data());
}
})
.catch(err => {
console.log('Error getting document', err);
});
I Encountered Same Problem recently while using Firebase Firestore and i used following approach to overcome it.
mDb.collection("Users").document(mAuth.getUid()).collection("tasks").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
if (task.getResult().isEmpty()){
Log.d("Test","Empty Data");
}else{
//Documents Found . add your Business logic here
}
}
}
});
task.getResult().isEmpty() provides solution that if documents against our query was found or not
Check this :)
var doc = firestore.collection('some_collection').doc('some_doc');
doc.get().then((docData) => {
if (docData.exists) {
// document exists (online/offline)
} else {
// document does not exist (only on online)
}
}).catch((fail) => {
// Either
// 1. failed to read due to some reason such as permission denied ( online )
// 2. failed because document does not exists on local storage ( offline )
});
If for whatever reason you wanted to use an observable and rxjs in angular instead of a promise:
this.afs.doc('cities', "SF")
.valueChanges()
.pipe(
take(1),
tap((doc: any) => {
if (doc) {
console.log("exists");
return;
}
console.log("nope")
}));
If the model contains too much fields, would be a better idea to apply a field mask on the CollectionReference::get()
result (let's save more google cloud traffic plan, \o/). So would be a good idea choose to use the CollectionReference::select()
+ CollectionReference::where()
to select only what we want to get from the firestore.
Supposing we have the same collection schema as firestore cities example, but with an id
field in our doc with the same value of the doc::id
. Then you can do:
var docRef = db.collection("cities").select("id").where("id", "==", "SF");
docRef.get().then(function(doc) {
if (!doc.empty) {
console.log("Document data:", doc[0].data());
} else {
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});
Now we download just the city::id
instead of download entire doc just to check if it exists.
Depending on which library you are using, it may be an observable instead of a promise. Only a promise will have the 'then' statement. You can use the 'doc' method instead of the collection.doc method, or toPromise() etc. Here is an example with the doc method:
let userRef = this.afs.firestore.doc(`users/${uid}`)
.get()
.then((doc) => {
if (!doc.exists) {
} else {
}
});
})
Hope this helps...