I have an app where a Firestore field value decreases by 45 every time a specific button is pressed.
I achieved this by using Firestore's FieldValue.increment()
as shown below:
FirebaseFirestore.instance.collection('users').get().then((_) async {
await FirebaseFirestore.instance.collection('users').doc(uid).update({
"example": FieldValue.increment(-45),
});
});
The problem is that I can't let the field example
reach less than zero.
I tried using the .where()
method, but it doesn't apply for specific documents, in this case, the current user document.
Future<void> example() {
return FirebaseFirestore.instance
.collection('users')
.where('example', isLessThan: 45)
.get()
.then(((value) {
print('subtracting results in a negative value');
}));
}
As it is clearly stated in the documentation, "only documents satisfying provided condition are included in the result set", it is evident that document-specific queries cannot be made, therefore my problem cannot be solved this way.
Ideally, an if
condition where a field reference meets the condition (< 45
) would solve the problem, but as far as I'm concerned, Firestore doesn't currently support a FieldReference, as opposed to CollectionReference
and DocumentReference
.
I'm relatively new to Flutter and I've been working with Firebase since quite recently, so any help and/or advice is greatly appreciated :)
CodePudding user response:
You can get the doc reference first, check the value and only increment if it complies with the if.
I do not come from Dart language background so feel free do correct the syntax. But hopefully you will get an idea.
Ex:
final userRef = await FirebaseFirestore.instance.collection('users').doc(uid)
userRef.get().then(res=>{
if(res.example > 45){
userRef.update({
"example": FieldValue.increment(-45),
})
}
})
CodePudding user response:
Instead of (or maybe in addition to) doing this in your code, I recommend doing it in Firebase's security rules. Since these rules are enforced on the server, there is no way for even a malicious client to circumvent then.
To validate that the example
field never becomes negative, you can do:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{user} {
allow write: if request.resource.data.example > 0;
}
}
}