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

时间:2020-09-09 21:17:31

标签: firebase flutter google-cloud-firestore

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

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

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(),
                );
              },
            ),
          ),

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

3 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:1)

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

您需要执行查询以获取单个文档,然后才能获取每个文档的子集合。

您可以使用抖动here找到一个很好的例子。

答案 2 :(得分:0)

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

    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;

}

在 bloc 中:我有 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);
}}}