【问题标题】:Flutter Firestore Update WhereFlutter Firestore 更新在哪里
【发布时间】:2022-01-03 17:03:10
【问题描述】:

我正在尝试运行一个查询,该查询在给定 where 子句的情况下检索单行并更新它。我了解 Firebase 不支持 UpdateWhere 操作,因此我尝试改用 Transaction

我很难让它工作,也许我太习惯 sql dbs... 这是我的坏代码

try {
    final whereQuery = _db
        .doc(userPath(user))
        .collection("someInnerCollection")
        .where("active", isEqualTo: true)
        .limit(1);

    await _db.runTransaction((transaction) async {
        final entry = await transaction.get(whereQuery);  // This doesn't compile as .get doesn't take in a query
        await transaction.update(entry, {
            "someValue": "newValue",
        });
    });
} catch (e) {
    ...
}

【问题讨论】:

    标签: firebase flutter google-cloud-firestore


    【解决方案1】:

    根据我所做的测试,我建议以下内容来实现您提到的:

    基于以下answer

    从 API 文档中可以看出,where() 返回一个 Query 对象。这不是 DocumentReference。

    即使您认为查询只会返回一个文档,您仍然必须编写代码来处理它可能在QuerySnapshot 对象中返回零个或多个文档的事实。我建议查看documentation on queries 以查看示例。

    在进行查询咨询后,您必须获得该给定结果的DocumentReference

    然后,您可以使用该引用来更新 Batched writes 中的字段

    try {
        final post = await firestore
            .collection('someInnerCollection')
            .where('active', isEqualTo: true)
            .limit(1)
            .get()
            .then((QuerySnapshot snapshot) {
                //Here we get the document reference and return to the post variable.
                return snapshot.docs[0].reference;
            });
    
        var batch = firestore.batch();
        //Updates the field value, using post as document reference
        batch.update(post, { 'someValue': 'newValue' }); 
        batch.commit();
        
    } catch (e) {
        print(e);
    }
    

    【讨论】:

    • 这正是我最终所做的!不错
    【解决方案2】:

    您在update() 操作中将DocumentSnapshot 传回,而不是DocumentReference 本身。尝试像这样重构:

    final docRefToUpdate = _db.collection("colName").doc("docId");
    
    await _db.runTransaction((transaction) async {
      final entry = await transaction.get() // <-- DocRef of document to update in get() here
      await transaction.update(docRefToUpdate, {
        // Pass the DocumentReference here ^^
        "someValue": "newValue",
      });
    });
    

    【讨论】:

    • 您必须通过从 entry. 读取文档 ID 在事务本身中创建 docRefToUpdate
    • 是的,您在正确的轨道上,但不幸的是transaction.get() 不接受查询,而是接受文档参考。这就是问题本身,因为我不知道如何在事务中执行 whereQuery
    • @Martin 是的。如果您尝试更新多个文档,那么Batched Writes 也可能是一个可行的选择。您必须运行查询,然后遍历所有匹配的文档并将它们添加到批量更新中并提交。
    • 来自FlutterFire's documentation, "当您想根据当前值或另一个字段的值更新字段时,事务很有用。如果您想编写多个文档而不使用记录当前状态,应该使用批量写入。”
    • 我不确定我是否了解您的最新更新。你没有在transaction.get() 中传递任何东西。我正在尝试更新仅一个条目/文档,我只想在单个事务中进行位置/更新。
    【解决方案3】:

    您可以使用集合引用,然后使用 .update() 更新单个字段。

    final CollectionReference collectionReference = FirebaseFirestore.instance.collection('users');
    
    await collectionReference.doc(user.uid).collection('yourNewCollection').doc('yourDocumentInsideNestedCollection').update({
            'singleField': 'whatever you want,
          });
    

    使用“where”的相同代码

    collectionReference.doc(user.uid).collection('yourNewCollection').doc().where('singleField', isEqualTo: yourValue).update({
                'singleField': 'whatever you want,
              });
    

    【讨论】:

    • 我需要事先执行 where 语句。我正在更新嵌套集合中的特定条目。
    • 查看上面的嵌套集合修改代码
    • 我不知道 yourDocumentInsideNestedCollection 这就是为什么我需要运行 where 子句...问题是我是否可以在事务中运行所有这些,例如获取 id 和更新的 where 子句
    • 您可以在集合参考中使用 where 我相信让我看看我能找到什么
    • 请查看上面修改后的代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2020-08-01
    • 2012-12-01
    • 2015-06-16
    • 1970-01-01
    相关资源
    最近更新 更多