有没有办法避免 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 , 而不是 CollectionReferenceDocumentReference.

我对 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 对我的问题的帮助。