You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何获取Firestore子集合Products的全部数据?

获取Firestore子集合全部数据的解决方案

问题描述

我的Firestore集合结构如下:
firestore集合结构

Products子集合中的文档带有productName字段。目前我能通过快照获取列表名称,代码如下:

CloudShoppingListsCart.fromSnapshot(QueryDocumentSnapshot<Map<String, dynamic>> snapshot, this.products)
  : shoppingListId = snapshot.id,
    name = snapshot.data()['name'] as String;

但我不知道如何像访问snapshot.data()那样直接获取products子集合及其字段。当前调用fromSnapshot的方法是:

Stream<Iterable<CloudShoppingListsCart>> getShoppingCartListDetails({required String shoppingCartListId}){

final shoppingList = FirebaseFirestore.instance.collection(shoppingListCollectionName)
    .doc(shoppingCartListId).collection(shoppingListCartCollectionName).snapshots().map((event) =>
    event.docs
        .map((doc) => CloudShoppingListsCart.fromSnapshot(doc, [])));

return shoppingList;

我希望能获取产品名称并在ListTile中显示,示例代码如下:

return ListTile(
  leading: const Icon(Icons.list),
  trailing: const Text(
     "GFG",
     style: TextStyle(color: Colors.green, fontSize: 15),),

  title: Text('List item $productsName'));

目前已经能在Column中显示列表名称,需要解决获取子集合数据并展示的问题。


解决方案

Firestore无法通过父文档快照直接获取子集合数据,必须单独发起子集合查询。以下是具体实现步骤:

1. 完善数据模型

先定义产品模型,并更新购物车模型以存储产品列表:

// 产品模型
class CloudProduct {
  final String productId;
  final String productName;

  CloudProduct({required this.productId, required this.productName});

  factory CloudProduct.fromSnapshot(QueryDocumentSnapshot<Map<String, dynamic>> snapshot) {
    return CloudProduct(
      productId: snapshot.id,
      productName: snapshot.data()['productName'] as String,
    );
  }
}

// 购物车模型
class CloudShoppingListsCart {
  final String shoppingListId;
  final String name;
  final List<CloudProduct> products;

  CloudShoppingListsCart({
    required this.shoppingListId,
    required this.name,
    required this.products,
  });

  factory CloudShoppingListsCart.fromSnapshot(
    QueryDocumentSnapshot<Map<String, dynamic>> snapshot,
    List<CloudProduct> products,
  ) {
    return CloudShoppingListsCart(
      shoppingListId: snapshot.id,
      name: snapshot.data()['name'] as String,
      products: products,
    );
  }
}

2. 修改数据流获取逻辑

在获取购物车列表的同时,异步查询每个购物车对应的products子集合:

Stream<Iterable<CloudShoppingListsCart>> getShoppingCartListDetails({required String shoppingCartListId}) {
  return FirebaseFirestore.instance
      .collection(shoppingListCollectionName)
      .doc(shoppingCartListId)
      .collection(shoppingListCartCollectionName)
      .snapshots()
      .asyncMap((event) async {
    // 遍历每个购物车文档,并行查询子集合数据
    final futures = event.docs.map((doc) async {
      final productsSnapshot = await FirebaseFirestore.instance
          .collection(shoppingListCollectionName)
          .doc(shoppingCartListId)
          .collection(shoppingListCartCollectionName)
          .doc(doc.id)
          .collection('products') // 替换为你的products子集合实际名称
          .get();
      final products = productsSnapshot.docs.map(CloudProduct.fromSnapshot).toList();
      return CloudShoppingListsCart.fromSnapshot(doc, products);
    });
    return await Future.wait(futures);
  });
}

3. 在UI中展示产品名称

使用StreamBuilder监听数据流,遍历购物车及对应的产品列表进行展示:

StreamBuilder<Iterable<CloudShoppingListsCart>>(
  stream: getShoppingCartListDetails(shoppingCartListId: '你的目标列表ID'),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const CircularProgressIndicator();
    }
    if (!snapshot.hasData || snapshot.data!.isEmpty) {
      return const Text('暂无数据');
    }
    final shoppingCarts = snapshot.data!;
    return Column(
      children: [
        // 先展示购物车列表名称
        ...shoppingCarts.map((cart) => Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text(cart.name, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            )),
        // 再展示每个购物车下的产品
        ...shoppingCarts.expand((cart) => cart.products.map((product) {
              return ListTile(
                leading: const Icon(Icons.list),
                trailing: const Text(
                  "GFG",
                  style: TextStyle(color: Colors.green, fontSize: 15),
                ),
                title: Text('List item ${product.productName}'),
              );
            })),
      ],
    );
  },
)

注意事项

  • 确保子集合名称与Firestore控制台中的完全一致
  • 若数据量较大,可考虑分页加载或使用limit()优化性能
  • 可添加try-catch块处理查询过程中的异常情况

内容的提问来源于stack exchange,提问作者jorge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:15:46