【问题标题】:Firebase Firestore atomic Transactions For syncing document with TextField in FlutterFirebase Firestore atomic Transactions 用于在 Flutter 中将文档与 TextField 同步
【发布时间】:2021-11-16 02:11:09
【问题描述】:

我是 firebase 和 firestore 的新手,在将 TextField 数据存储在云 Firestore 中并对它们执行事务时遇到问题,我怀疑我们是否可以执行更新事务,如果文档不存在,那么它应该创建然后执行交易...

我想实现以下目标:

  1. 我想将当前用户 uidemail 存储在“X”集合的文档中。

  2. 我想对“X”集合的“Y”(这里 Y 是 uid/email)文档执行交易更新 此外,如果该用户的该文档不存在,它应该创建一个然后执行事务,然后如果用户在没有按下save 按钮的情况下退出文本字段,那么它应该从firestore中删除。

  3. 我想传递用户的 uid、title、tag、desc 等。作为文档中的字段(docID 应该是当前用户的emailuser's uid)。

到目前为止,我能够从 auth 类获取用户并使用 initState() 在我当前的工作类中访问它,但我不知道如何获取该 uid/电子邮件并将其存储到“X”集合文档中

将数据传递给 firebase 的代码是,

 Future<void> postQ() async {
    FirebaseFirestore db = FirebaseFirestore.instance;
    CollectionReference question =
        FirebaseFirestore.instance.collection('question');
    DocumentReference cUser = question.doc(_currentUser.uid);
      // in the above line I tried to get currentuser uid but that also not working and below I want to pass title,etc... in the doc of that current user with fields title, tag, desc, users uid and email and docID should be the email or user's uid....
      await db.runTransaction((transaction) async {
      String title = title_Controller.text;
      String desc = desc_Controller.text;
      String tag = tag_Controller.text;
      DocumentReference qRef = db.collection('question').doc();
      DocumentSnapshot snapshot = await transaction.get(qRef);
      // int likesCount = snapshot.data['likes'];
      await transaction.update(qRef, {
        // 'authorId': _currentUser,
        'title': title,
        'desc': desc,
        'tag': tag,
      });
    });
  }
}

但上面的代码将我抛出以下消息,所以我如何在运行事务之前创建一个,并且该文档应该将当前用户 uid 和电子邮件作为字段之一。

无法在不存在的文档上运行事务

以下是从终端中的文本字段获取不断更新的工作代码,

class CreateQ extends StatefulWidget {
  final User user;
  CreateQ({Key? key, required this.user}) : super(key: key);

  @override
  State<CreateQ> createState() => _CreateQState();
}

class _CreateQState extends State<CreateQ> {
  final title_Controller = TextEditingController();
  final desc_Controller = TextEditingController();
  final tag_Controller = TextEditingController();
  @override
  void initState() {
    super.initState();
    _currentUser = widget.user;
    super.initState();
    // Start listening to changes.
    title_Controller.addListener(_latestTitle);
    desc_Controller.addListener(_latestDesc);
    tag_Controller.addListener(_latestTag);
  }

  // @override
  // void dispose() {
  // Clean up the controller when the widget is removed from the widget tree.
  // This also removes the latestvalue listener.
  // title_Controller.dispose();
  // super.dispose();
  // }

  void _latestTitle() {
    print('Title text field: ${title_Controller.text}');
  }

  void _latestDesc() {
    print('Desc text field: ${desc_Controller.text}');
  }

  void _latestTag() {
    print('Tag text field: ${tag_Controller.text}');
  }

  // ignore: unused_field
  late User _currentUser;
  

  UploadTask? task;
  File? file;

  @override
  Widget build(BuildContext context) {
 body: Container(
          padding: EdgeInsets.all(32),
          child: ListView(shrinkWrap: true, children: [
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                TextField(
                  controller: title_Controller,
                  decoration: InputDecoration(
                      hintText: 'Your Title here',
                      counterText: '',
                      border: OutlineInputBorder()),
                  keyboardType: TextInputType.multiline,
                  maxLines: 1,
                  maxLength: 100,
                ),
                SizedBox(height: 8),
                TextField(
                  controller: desc_Controller,
                  decoration: InputDecoration(
                      hintText:
                          'Enter Your Description here... ',
                      border: OutlineInputBorder()),
                  keyboardType: TextInputType.multiline,
                  maxLines: 15,
                  maxLength: 10000,
                ),
                SizedBox(height: 8),
                TextField(
                  controller: tag_Controller,
                  decoration: InputDecoration(
                      hintText:
                          'Add up to 5 tags to describe what your question is about',
                      counterText: '',
                      border: OutlineInputBorder()),
                  keyboardType: TextInputType.text,
                  maxLines: 1,
                  maxLength: 100,
                ),  ));
  }

我尝试使用 set() 方法,但会引发错误如果有人可以提供当前问题的工作示例,那将非常有帮助, 谢谢...

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore flutter-web


    【解决方案1】:

    如果文档不存在,调用 update 将不会创建文档。 如果文档不存在,Set 将创建/更新文档。 但是,您可以检查文档是否存在,然后根据需要使用 set 或 update。

     DocumentSnapshot snapshot = await transaction.get(qRef);
    if(snapshot.exists){
      //run update/set operation
    }else{
     // run set operation
    }
    

    无论您是否使用事务,设置和更新都将按照我上面提到的方式工作。如果对任何一个文档的任何集合/更新失败,事务使您能够撤消任何文档操作。

    您可以通过这里了解 set 和 update 之间的区别。 https://firebase.google.com/docs/firestore/manage-data/add-data

    【讨论】:

    • 非常感谢它现在可以工作,但是我如何将该文档命名为在“X”集合中创建该文档的特定用户的名称...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    • 2021-04-27
    相关资源
    最近更新 更多