【问题标题】:Flutter Firestore update if exist if not create如果不创建则 Flutter Firestore 更新(如果存在)
【发布时间】:2019-02-16 13:12:12
【问题描述】:

我想知道特定文档是否存在,更新该文档,如果不存在,是否可以在 Firestore 中创建该文档。 例如,用户输入了一些带有帖子的标签,然后看起来像这样
Firestore.instance.collection('tags').document(tag here).updateData()。 如果该文档不存在,有什么办法,然后创建方法还是我必须在编写之前检查它是否存在?

【问题讨论】:

  • 只是评论说这也与我的 web sdk 相关,并且 Doug 在下面的回答也适用于此。

标签: flutter google-cloud-firestore


【解决方案1】:

更新

在较新的 Firebase SDK 上,语法发生了变化; Firebase 是 FirebaseFirestore,不推荐使用 setData 以支持 set + SetOptions。

FirebaseFirestore.instance.
  collection('tags').
  document(tag).
  set(data, SetOptions(merge: true))

@Doug 是对的,Flutter Firestore API 中有一个选项:

Firestore.instance.
  collection('tags').
  document(tag here).
  setData(data, merge: true)

来自文档:

setData(Map<String, dynamic> data, {bool merge: false}) → Future<void>

写入此 DocumentReference 引用的文档。如果文档尚不存在,则会创建它。

如果 merge 为 true,则提供的数据将合并到现有文档中,而不是覆盖。

将其与来自updateData 的文档进行比较,后者明显失败。

updateData(Map<String, dynamic> data) → Future<void>

更新此 DocumentReference 引用的文档中的字段。

如果尚不存在文档,则更新将失败

【讨论】:

  • If no document exists yet, the update will fail 这会导致任何可能导致应用崩溃的错误吗?
  • 我是否可以更新与给定单个/多个条件匹配的所有文档的字段值?例如。 FirebaseFirestore.instance .collection('messages') .where('encSenderUId', isEqualTo: widget.encUId) .where('encReceiverUId', isEqualTo: _loggedInUserId) ...update Map code.... 请建议。谢谢。
  • 我也遇到了同样的问题,请你回答这个stackoverflow.com/q/69287110/13984728
【解决方案2】:

我不知道它是如何与 Flutter 一起工作的(我一生中没有写过一行 Dart),但其他客户端 API 允许 set() 的第二个参数(或者在你的情况下为 setData() ) 允许创建一个不存在的文档,或者在它已经存在的情况下合并。

有关其他语言的示例,请参阅documentation。这可能只是将{ merge: true } 作为第二个参数传递的问题,就像网络示例一样,或者可能像Java 一样使用SetOptions.merge()

【讨论】:

    【解决方案3】:

    看来从 2020-03-31 开始,是的,您必须先检查该文档是否存在。 setData(data, merge: true) 实际上并不服从 merge 参数。 Here is the relevant GitHub issue

    我得到的行为等同于普通的setData(),因此它会默默地覆盖任何现有数据。昂贵的解决方法:

    final Firestore _db = Firestore.instance;
    final collection = 'my_collection';
    final documentId = 'my_document';
    final snapShot = await _db.collection(collection).document(documentId).get();
    if(snapShot.exists){
      _db.collection(collection).document(documentId).updateData(myMap);
    } else {
      _db.collection(collection).document(documentId).setData(myMap);
    }
    

    【讨论】:

    • 我想做类似的事情,但我不想使用 documentId,我的查询是基于其他列的..你能帮忙吗?
    • 如果我理解正确,在上面的示例中,您可以将snapShot = 中的查询更改为您需要的任何内容。然后,在第一种情况下,snapShot.exists,您将使用快照的文档 ID 替换 .document(documentId).document(snapShot.document.documentId),即使您没有在查询中使用它。条件的后半部分可以保持不变,按照您通常的方式设置新文档的 ID。
    【解决方案4】:

    2021 年更新:

    在文档上使用set,并提供SetOptionsmerge: true。来自docs

    在文档上设置数据,覆盖任何现有数据。如果文档尚不存在,则会创建它。

    如果提供了 SetOptions,数据将被合并到现有文档中,而不是覆盖。

    var collection = FirebaseFirestore.instance.collection('collection');
    collection
        .doc('doc_id')
        .set(yourData, SetOptions(merge: true));
    

    【讨论】:

      【解决方案5】:

      你想更新,最好的办法是:

      Future updateUserFirestore(
        String name,
        String dob,
        String email,
        String sex
      ) {
      
          return _getUserDetailsDocumentRef().update({
            'name': name,
            'dob': dob,
            'email': email,
            'sex': sex
          }).catchError((e) => {
      
            _getUserDetailsDocumentRef().set({
              'name': name,
              'dob': dob,
              'email': email,
              'sex': sex
            }, SetOptions(merge: true))
          });
      }
      

      【讨论】:

        猜你喜欢
        • 2016-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-26
        • 2022-11-18
        • 2010-10-16
        • 2017-08-30
        • 2019-02-16
        相关资源
        最近更新 更多