繁体   English   中英

如何从Flutter上的Firestore获取collections的列表和一个集合下所有字段的列表?

[英]How to get a list of collections and a list of all fields under a collection from Firestore on Flutter?

我正在制作一个对话启动器应用程序,在这个应用程序中,用户可以选择不同类别的问题。 这是用户登录后应用程序主页的样子:

应用程序主页的图像

我目前列出所有这些类别的方式是将类别名称保存为我称为“用户”的集合下的文档 ID。 然后我使用以下代码片段获取所有这些文档 ID/类别并将它们添加到List中。 然后,我使用FutureBuilder将此List<String>转换为按钮List 下面的代码可以帮助阐明我在做什么:

第 1 步:获取所有文档 ID/类别名称:

  List<String> questionCategories = [];


 Future getCategories() async {
    await FirebaseFirestore.instance
        .collection('users')
        .get()
        .then((snapshot) => snapshot.docs.forEach(
              (document) {
                questionCategories.add(document.reference.id);
            ));
  }

第 2 步:使用 questionCategories List<String>创建按钮List

 FutureBuilder(
            future: getCategories(),
            builder: (context, snapshot) {
              return SizedBox(
                height: MediaQuery.of(context).size.height - 250,
                child: ListView.builder(
                  itemCount: questionCategories.length,
                  itemBuilder: (context, index) {
                    return Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: GestureDetector(
                          onTap: //questionPageInit,
                              () {
                            print(collectionList);
                            Navigator.push(context,
                                MaterialPageRoute(builder: (context) {
                              //return ForgotPasswordPage();
                              return CategoryPage(
                                categoryName: questionCategories[index],
                              );
                            }));
                          },
                          child: Container(
                              padding: EdgeInsets.all(20),
                              decoration: BoxDecoration(
                                color: Colors.deepPurple,
                                borderRadius: BorderRadius.circular(12),
                              ),
                              child: Center(
                                  child: Text(questionCategories[index],
                                      style: TextStyle(
                                        color: Colors.white,
                                        fontWeight: FontWeight.bold,
                                        fontSize: 18,
                                      ))))),
                    );
                  },
                ),
              );
            },
          ),

选择类别后,问题卡上一次显示一个问题,在该卡下方,用户可以在下一个和上一个问题之间切换,然后洗牌。 这个页面看起来像这样:

应用问题页面的图片

我显示这些问题的方法是获取文档 ID 下所有字段的List并将其添加到List<String> 当用户按下 shuffle、next 或 previous 时,我只需更改一个全局索引变量并再次设置 state 以根据哪个问题出现在List中的特定索引处显示一个新问题。 下面的代码应该有助于阐明我在做什么:

void printAllQuestionsList(snapshot) {
    Map<String, dynamic> data = snapshot.data() as Map<String, dynamic>;
    for (String key in data.keys) {
      print(key + data[key]!);
      questionsList.add(data[key]);
    }
  }

  Future getQuestionList() async {
    if (questIndex > 1) {
      return;
    }
    if (widget.categoryName == "ALL") {
      await FirebaseFirestore.instance
          .collection('users')
          .get()
          .then(((snapshot) => snapshot.docs.forEach((document) {
                print(document.reference.id);
                FirebaseFirestore.instance
                    .collection('users')
                    .doc(document.reference.id)
                    .get()
                    .then((snapshot) => {printAllQuestionsList(snapshot)});
              })));
    } else {
      await FirebaseFirestore.instance
          .collection('users')
          .doc(widget.categoryName)
          .get()
          .then((snapshot) => {printQuestionList(snapshot)});
    }
  }

在小部件 Build function 中,我有这段代码:

FutureBuilder(
                    future: getQuestionList(),
                    builder: ((context, snapshot) {
                      // return TextField(
                      //   decoration: InputDecoration(
                      //     enabledBorder: OutlineInputBorder(
                      //       borderSide: BorderSide(
                      //         width: 5, //<-- SEE HERE
                      //         color: Colors.greenAccent,
                      //       ),
                      //       borderRadius: BorderRadius.circular(50.0),
                      //     ),
                      //   ),
                      // );f
                      return Container(
                          margin: const EdgeInsets.all(15.0),
                          padding: const EdgeInsets.all(10.0),
                          width: 350,
                          height: 350,
                          decoration: BoxDecoration(
                              color: Colors.deepPurple[200],
                              borderRadius:
                                  BorderRadius.all(Radius.circular(20))
                              // border: Border.all(color: Colors.blueAccent)
                              ),
                          child: Align(
                            alignment: Alignment.center,
                            child: SingleChildScrollView(
                              scrollDirection: Axis.vertical,
                              child: Text(
                                questionsList[index],
                                style: TextStyle(
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold,
                                  fontSize: 32,
                                ),
                                textDirection: TextDirection.ltr,
                                textAlign: TextAlign.center,
                              ),
                            ),
                          ));
                    }))

我在这个应用程序上有第二个页面,用于向现有或新Category提交问题(如果他们输入我设置的正确密码)。

提交问题页面的图像

我使用以下代码片段来执行此操作:

  Future addQuestion(String category, String question) async {
    var usersRef = questionCollection.doc(category);

    await FirebaseFirestore.instance
        .collection('users')
        .get()
        .then((snapshot) => snapshot.docs.forEach(
              (document) {
                existingQuestionCategories.add(document.reference.id);
              },
            ));

    if (existingQuestionCategories.contains(category)) {
      print("Document Exists! ");
      questionCollection.doc(category).update({question: question});
    } else {
      // FieldPath pathfield = FieldPath.fromString(category);
      //String category2 = pathfield.category;
      print('No such document exists so now about to set document anew!');
      print(category);
      FirebaseFirestore.instance
          .collection("users")
          .doc(category)
          .set({question: question});
    }
  }

这是我的 Firestore 数据库的组织方式

Firestore 数据库组织的图像

用户 -> 问题类别(文档 ID) -> 问题键:问题字段

这就是我想要设置的方式:

Users -> Autogenerated ID -> Question Categories as collections -> question key (titled “question”): question key (“实际问题在这里)

这样,在每个集合下,我还可以列出与问题相关的字段,例如它是轻度、中度还是深度,我可以稍后添加。

我也想这样做,因为有时当我尝试使用我的提交问题页面时,我输入的问题没有被提交,我认为这可能是因为我在文档 ID 下而不是在集合下提交问题.

总之,我的问题是如何从我的数据库中将我主页上的所有问题列为 collections 的列表? 此外,这将如何更改我编写的代码(1)在单击类别名称时查看各个卡片上的问题,以及(2)向特定类别/集合提交新问题? 如果我想做的事情不能按照我想要的方式完成,是否有更有效的方法来做到这一点?

我尝试在 Flutter 上搜索如何在 Firestore 上获取 collections 的列表,但我找到的所有答案都为我提供了一个关于如何获取文档 ID 下的字段List的解决方案。 这就是我问这个问题的原因。

实际上,Flutter 的 Firebase SDK(我假设是 Android/IOS)没有任何预构建的方法来获取 firestore 数据库中所有 collections 的List

但是,据我所知,您可以使用云 function 来获取它们,例如使用Node.js编写的示例,请参阅thisthis

如果你愿意写一个云 function 来在你的 flutter 项目上实现这一点,那很好。

但是,如果您对此感兴趣,我可以考虑一个实用的解决方案:

  • 创建另一个集合/文档,在其中列出您的 firestore collections,对于您的先例 collections,我想您别无选择,只能手动添加它们,但是如果您要为项目的未来创建新的 collections,您可以实施通用方法检查集合名称是否存在,并根据它采取行动。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM