*AngularFireStore:
Is there a way to check if a document already exists in the database?
Couldn't find an example.
Thank you
Don't think you can do it with AFS, and might have to rely on the underlying framework:
this.afs.firestore.doc('/users/asfaf').get()
.then(docSnapshot => {
if (docSnapshot.exists) {
// do something
}
});
this.afs.doc('/path').take(1).do(d => d.payload.exists())
As of 5.0 rc3 empty sets/docs should be handled correctly.
I am working on an API to make return or create easier.
@jamesdaniels I import the operator take already but i got error
i can't use doc with take operator.
I'm doing it manually - hopefully there is a better way?
this.dataDoc = this.myDataCollectionRef.doc(id);
this.data = this.dataDoc.snapshotChanges().map(action => {
if (action.payload.exists === false) {
return null;
} else {
const data = action.payload.data() as Whatever;
const id = action.payload.id;
return { id, ...data };;
});
Might be incorrect usage of snapshotChanges(), but its able to determine if something is there. If you wanted to manually create it, I believe you could do that once you've determined it doesn't exist.
Just popping in to report that neither take() nor do() work (exist) for me on AngularFirestoreDocument
Currently handling this by attempting an update and setting on error as such:
this.afs.doc(`users/${uid}`)
.update({data})
.then(() => {
// update successful (document exists)
})
.catch((error) => {
// console.log('Error updating user', error); // (document does not exists)
this.afs.doc(`users/${result.uid}`)
.set({data});
});
@jamesdaniels example is missing somethings:
.snapshotChanges()So,
this.afs.doc('/path').snapshotChanges().take(1).do(d => d.payload.exists)
i check simply , not sure if that is the right way to do ..
const userRef: AngularFirestoreDocumentusers/${user.uid});
userRef.valueChanges().subscribe(res=>{
if(res){
// do your perform
}
} );
And if i need a query like : this.afs.collection('users', ref => ref.where('email', '==', email)) how i can do that?
Here's a variation of @sneurlax's example:
//Create an empty document, or do nothing if it exists.
this.afs.doc('users/sam').set({ }, { merge: true });
//Create a document with name property set to 'Sam'.
//If document already exists, it will still set the name property to 'Sam'
this.afs.doc('users/sam').set({ name: 'Sam' }, { merge: true });
@buchmiller
But by doing so, it will be a write in the document.
A write in the document is more costly in terms of pricing according to firebase pricing.
If we can read before we write it will be more cost efficient :)
How about searching 2 parameters, like username and email?
I am looking for username and email that I type in input.
I think it could be in 2 ways:
Maybe we can do all in one query in where clause using OR statement. I am not sure if firestore support it.
I think we can search the username first. If it return null, we continue search the email. I am looking for this possible way. Any suggestion?
FTR: https://angularfirebase.com/lessons/firestore-advanced-usage-angularfire/#4-Upsert-Update-or-Create-Method
// *** Usage
this.db.upsert('notes/xyz', { content: 'hello dude'})
// *** Code
upsert<T>(ref: DocPredicate<T>, data: any) {
const doc = this.doc(ref).snapshotChanges().take(1).toPromise()
return doc.then(snap => {
return snap.payload.exists ? this.update(ref, data) : this.set(ref, data) })
}
You can use
db.doc('collectionName/documentId').ref.get().then((documentSnapshot) => {
console.log(documentSnapshot.exists);
});
Hello,
I am using firestore from firebase(npm) and the property .exists was not available on the querySnapshot:
https://firebase.google.com/docs/firestore/query-data/get-data
db.collection("cities").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
});
querySnapshot in that context have a property .empty that I use to know if I get a document or not from the query. Hope this helps too.
@mk4yukkalab do you got workaround to ur concern
And if i need a query like : this.afs.collection('users', ref => ref.where('email', '==', email)) how i can do that?
do you know how do that ??
@mk4yukkalab do you got workaround to ur concern
And if i need a query like : this.afs.collection('users', ref => ref.where('email', '==', email)) how i can do that?
do you know how do that ??
firestore
.collection('YourCollection')
.doc('YourDocumentID').set(
{a: {b: {c: true}}},
{merge: true}
)
This one should work
@mk4yukkalab @Hanan0o0 @Vino16491
in angular 6 I manage like that
this.afs.collection('users', (ref) => ref.where('email', '==', email).limit(1)).get().subscribe(users => {
if(users.size >= 0)
...do smthg
})
Currently handling this by attempting an
updateandsetting on error as such:this.afs.doc(`users/${uid}`) .update({data}) .then(() => { // update successful (document exists) }) .catch((error) => { // console.log('Error updating user', error); // (document does not exists) this.afs.doc(`users/${result.uid}`) .set({data}); });
Trying to do something similar in iOS. I think this should be done in a transaction though because there's plenty of time for data to be written with the ID between the update response and the set. Also, I'm questioning whether this is a good solution since we're using an error in order to proceed.
@larssn solution still works as of date.
@buchmiller
But by doing so, it will be a write in the document.
A write in the document is more costly in terms of pricing according to firebase pricing.
If we can read before we write it will be more cost efficient :)
Are you sure? For me it makes more sense, not be a cost in case of update. So, the cost will be the same as @sneurlax method.
For Android in Kotlin:
````
fun insertOrUpdate() {
val mapFields = hashMapOf(
"key1" to "val1",
"key2" to "val2",
"key3" to "val3"
)
val dbInstance = FirebaseFirestore.getInstance()
val docRef: DocumentReference = dbInstance.collection("my_collection_id")
.document("my_doc_id")
docRef.get()
.addOnSuccessListener {
if (it.exists()) {
docRef.update(mapFields)
.addOnSuccessListener { }
.addOnFailureListener { }
} else {
docRef.set(mapFields)
.addOnSuccessListener { }
.addOnFailureListener { }
}
}
.addOnFailureListener { }
}
And if i need a query like : this.afs.collection('users', ref => ref.where('email', '==', email)) how i can do that?
I am not an expert so there may be better ways, but here is what I did in that situation:
this.afs.collection('eicpeople', ref => ref.where('familyKey', '==', person.familyKey))
.valueChanges().pipe(take(1)).subscribe(matchingRecs => {
if (matchingRecs.length > 0) // this is my equivalent to exists
else // this is no match
db.collection('users')
.where('user_id', '==', user.id)
.get()
.then(querySnapshot => {
if(querySnapshot.docChanges().length === 0){
//Add new user to DB
db.collection('users').add( user );
}
}).catch((err) => {
console.log(err);
});
The way I went about this a combo of creating my own unique ID based on the data by using a sha library (js-sha256), just JSON.stringify(data) to get your id then follow the approach above.
const sha = sha256(JSON.stringify({...data})).substring(0, 10);
this.db.doc(`${DATA}/${sha}`).set(data, {merge: true})
Data is always overwritten.
Don't think you can do it with AFS, and might have to rely on the underlying framework:
this.afs.firestore.doc('/users/asfaf').get() .then(docSnapshot => { if (docSnapshot.exists) { // do something } });
.then is not applicable after .get or valuechanges
I am also trying to find a solution for angular 8
All these code examples which use "docSnapshot.exists" checking, arent they forgetting that this is not a transaction, so it can not guarantee that by the time the client find out that doc does not exist and it triggers a create new doc, someone else might have created that doc, in between get() and set() calls ? (although its probability is less but not zero)
Thought Id share this...I am doing it like so:
const docRef = this.db.collection("user_flags").doc(this.user.id);
docRef.get().subscribe(doc => {
docRef[doc.exists ? 'update' : 'set']({
exampleFlag: true
})
})
any objections? If the doc exists it uses update, otherwise set.
Most helpful comment
Currently handling this by attempting an
updateandsetting on error as such: