如何使用 Flutter 获取 Firestore 中每个集合的子集合

Posted

技术标签:

【中文标题】如何使用 Flutter 获取 Firestore 中每个集合的子集合【英文标题】:How to get sub-collections of every collection in Firestore using Flutter 【发布时间】:2020-12-28 08:38:45 【问题描述】:

我正在构建一个任务管理应用程序,其中每个用户都有多个项目(集合),每个项目内部都有任务(集合),每个任务内部都有子任务。

我能够使用此代码检索所有项目:

User user = Provider.of<User>(context);
CollectionReference projects = Firestore.instance.collection('users').document(user.uid).collection("projects");

但我的问题是如何从每个项目中获取所有任务和子任务(如果存在)并将它们列出在 StreamBuilder 中?

这是我当前的代码:

Flexible(
            child: StreamBuilder<QuerySnapshot>(
              stream: projects.snapshots(),
              builder: (BuildContext context,
                  AsyncSnapshot<QuerySnapshot> snapshot) 
                if (snapshot.hasError) 
                  return Text('Something went wrong');
                

                if (snapshot.connectionState == ConnectionState.waiting) 
                  return Text("Loading");
                

                return new ListView(
                  children:
                      snapshot.data.documents.map((DocumentSnapshot document) 
                    return new ListTile(
                      title: new Text(document.data['project_name']),
                      subtitle: new Text(document.data['project_description']),
                    );
                  ).toList(),
                );
              ,
            ),
          ),

如果项目有任务,我想在项目描述下方显示它们,如果任务有子任务,我想在其父任务下方显示它们。

【问题讨论】:

您可能对此article 感兴趣,它解释了如何使用云函数检索文档的子集合列表。 【参考方案1】:

听起来您实际上是在问如何列出嵌套的子集合,这对于网络和移动客户端是不可能的。另见:

How to list subcollections in a Cloud Firestore document How to list subcollection on firestore?

此外,所有 Firestore 查询都是浅层的,这意味着它们一次只考虑一个集合中的文档。没有深度或递归查询。

考虑改为在文档中维护项目列表,您可以直接get()。您可以使用该列表直接查询每个子集合。

【讨论】:

【参考方案2】:

这种情况有不同的实现方式,基本上子集合位于一个文档下,查询标识一组文档,当您知道查询仅标识一个文档时,Firestore 客户端不知道,即使知道,它也不知道该文档的完整路径。

你需要执行一个查询来获取单个文档,然后你可以得到每个文档的子集合。

你可以使用flutter here找到一个很好的例子。

【讨论】:

【参考方案3】:

我遇到了类似的问题,并在流旁边使用了 bloc 提供程序, 我首先为 Json 解析创建了一个模型(在我的例子中,我有一个用户可以创建活动的应用程序,这些活动被保存为 UserData 集合中的子集合,文档 ID 是来自 FirebaseAuth 的用户 ID(现在是 Flutter 迁移中的用户). 目标是遍历每个用户的子集合 (UserCampaigns) 的 UserData 集合,并检索所有这些集合并使用 bloc.userCampaignRepository 显示在 UI 中:

    List<UserCampaignModel> UserCampaignList = [];
CreateListofAllUserCampaigns(QuerySnapshot snapshot) async 
var docs = snapshot.docs;
for (var Doc in docs) 
  UserCampaignList.add(
      UserCampaignModel.fromEntity(UserCampaignEntity.fromSnapshot(Doc)));

return UserCampaignList;

Stream<List<UserCampaignModel>> getListUserCampaigns() async* 
final collection = FirebaseFirestore.instance.collection('UserData');
final List list_of_users = await collection.get().then((value) => value.docs);
for (int i = 0; i < list_of_users.length; i++) 
  FirebaseFirestore.instance.collection("UserData")
      .doc(list_of_users[i].id.toString())
      .collection("UserCampaigns")
      .snapshots()
      .listen(CreateListofAllUserCampaigns);

yield UserCampaignList;

在集团中:我有 2 个事件,一个是通过监听流和调用加载器事件来启动事件加载。

     if (event is InitiateLoadOfAllUserCampaignsEvent) 
  yield AllUserCampaignsState.initial();
  try 
    
    _userCampaignSubscription?.cancel();
    _userCampaignSubscription = _userCampaignRepository
        .getListUserCampaigns()
        .listen((allCampaigns) 
          print("Load event is called");
      add(
        LoadAllUserCampaignsEvent(allUserCampaigns: allCampaigns),
      );
      
    );
   catch (e) 
    print("error is $e");
    yield AllUserCampaignsState.allUserCampaignLoadFailure();
  
 else if (event is LoadAllUserCampaignsEvent) 
  yield* _mapLoadAllUserCampaignsEventToState(event);

【讨论】:

以上是关于如何使用 Flutter 获取 Firestore 中每个集合的子集合的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Flutter 获取 Firestore 中每个集合的子集合

如何使用 Firestore 在 Flutter 中搜索文本

Flutter:使用 Streambuilder<QuerySnapshot> 时如何在 firestore 中获取特定文档

如何使用 graphql 从 Firebase 使用 Flutter 从 Cloud Firestore 获取数据?

Firestore / Flutter - 如何获取文档 ID?

如何从flutter中的firestore文档字段中获取数据?