有没有办法避免 Firestore 字段达到负值?
Is there a way to avoid a Firestore field from reaching a negative value?
我有一个应用程序,每次按下特定按钮时,Firestore 字段值都会减少 45。
我通过使用 Firestore 的 FieldValue.increment()
实现了这一点,如下所示:
FirebaseFirestore.instance.collection('users').get().then((_) async {
await FirebaseFirestore.instance.collection('users').doc(uid).update({
"example": FieldValue.increment(-45),
});
});
问题是我不能让字段 example
小于零。
我尝试使用 .where()
方法,但它不适用于特定文档,在本例中为当前用户文档。
Future<void> example() {
return FirebaseFirestore.instance
.collection('users')
.where('example', isLessThan: 45)
.get()
.then(((value) {
print('subtracting results in a negative value');
}));
}
正如文档中明确指出的那样,“只有满足提供条件的文档才会包含在结果集中”,显然无法进行特定于文档的查询,所以我的问题不能这样解决。
理想情况下,字段引用满足条件 (< 45
) 的 if
条件可以解决问题,但就我而言,Firestore 目前不支持 FieldReference , 而不是 CollectionReference
和 DocumentReference
.
我对 Flutter 比较陌生,最近才开始使用 Firebase,所以非常感谢任何帮助 and/or 建议 :)
你可以先获取doc reference,检查值,只有符合if才递增。
我没有 Dart 语言背景,所以请随时纠正语法。但希望你会有所了解。
例如:
final userRef = await FirebaseFirestore.instance.collection('users').doc(uid)
userRef.get().then(res=>{
if(res.example > 45){
userRef.update({
"example": FieldValue.increment(-45),
})
}
})
我建议您在 Firebase 的安全规则中执行此操作,而不是(或可能除此之外)在您的代码中执行此操作。由于这些规则是在服务器上强制执行的,因此即使是恶意客户端也无法规避。
要validate example
字段永远不会变为负值,您可以这样做:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{user} {
allow write: if request.resource.data.example > 0;
}
}
}
我可以解决! 如果您遇到同样的问题,请按以下方法解决。
我绕过并使用 transaction
而不是 FieldValue.update()
。
事务的工作方式有点不同,所以我建议先阅读 docs。
基本上,我做了以下事情:
void update() async {
await FirebaseFirestore.instance.runTransaction((transaction) async {
final snapshot = await transaction.get(docRef);
final amount = snapshot.get("example");
if (amount > 0) {
final newAmount = snapshot.get("example") - 1;
transaction.update(docRef, {"example": newAmount});
}
});
}
这样,我将当前的 example
字段值存储在 amount
中,如果它大于 0,那么它会自我更新并减去 1,从而避免它达到小于 0 .
虽然我使用了不同的方法,但我要感谢 Frank van Puffelen 和 Jiří Petera 对我的问题的帮助。
我有一个应用程序,每次按下特定按钮时,Firestore 字段值都会减少 45。
我通过使用 Firestore 的 FieldValue.increment()
实现了这一点,如下所示:
FirebaseFirestore.instance.collection('users').get().then((_) async {
await FirebaseFirestore.instance.collection('users').doc(uid).update({
"example": FieldValue.increment(-45),
});
});
问题是我不能让字段 example
小于零。
我尝试使用 .where()
方法,但它不适用于特定文档,在本例中为当前用户文档。
Future<void> example() {
return FirebaseFirestore.instance
.collection('users')
.where('example', isLessThan: 45)
.get()
.then(((value) {
print('subtracting results in a negative value');
}));
}
正如文档中明确指出的那样,“只有满足提供条件的文档才会包含在结果集中”,显然无法进行特定于文档的查询,所以我的问题不能这样解决。
理想情况下,字段引用满足条件 (< 45
) 的 if
条件可以解决问题,但就我而言,Firestore 目前不支持 FieldReference , 而不是 CollectionReference
和 DocumentReference
.
我对 Flutter 比较陌生,最近才开始使用 Firebase,所以非常感谢任何帮助 and/or 建议 :)
你可以先获取doc reference,检查值,只有符合if才递增。
我没有 Dart 语言背景,所以请随时纠正语法。但希望你会有所了解。
例如:
final userRef = await FirebaseFirestore.instance.collection('users').doc(uid)
userRef.get().then(res=>{
if(res.example > 45){
userRef.update({
"example": FieldValue.increment(-45),
})
}
})
我建议您在 Firebase 的安全规则中执行此操作,而不是(或可能除此之外)在您的代码中执行此操作。由于这些规则是在服务器上强制执行的,因此即使是恶意客户端也无法规避。
要validate example
字段永远不会变为负值,您可以这样做:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{user} {
allow write: if request.resource.data.example > 0;
}
}
}
我可以解决! 如果您遇到同样的问题,请按以下方法解决。
我绕过并使用 transaction
而不是 FieldValue.update()
。
事务的工作方式有点不同,所以我建议先阅读 docs。
基本上,我做了以下事情:
void update() async {
await FirebaseFirestore.instance.runTransaction((transaction) async {
final snapshot = await transaction.get(docRef);
final amount = snapshot.get("example");
if (amount > 0) {
final newAmount = snapshot.get("example") - 1;
transaction.update(docRef, {"example": newAmount});
}
});
}
这样,我将当前的 example
字段值存储在 amount
中,如果它大于 0,那么它会自我更新并减去 1,从而避免它达到小于 0 .
虽然我使用了不同的方法,但我要感谢 Frank van Puffelen 和 Jiří Petera 对我的问题的帮助。