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

如何从Firestore的users集合中获取用户关联的食谱数据?

从Firestore获取用户关联的食谱详情

根据你的Firestore结构(用户集合存储食谱ID列表,独立集合存储完整食谱数据),需要分两步完成查询:先获取用户关联的食谱ID列表,再根据ID批量查询完整食谱信息。

步骤说明

    1. 读取当前用户文档下colrecipes子集合中的recipeIDs数组(从截图看,该子集合下有一个文档包含此数组)
    1. 使用Firestore的whereIn方法,在主colrecipe集合中查询ID属于该数组的所有文档
  • 注意:whereIn最多支持50个元素,若食谱ID数量超过50,需要拆分数组分批查询后合并结果

代码实现示例

body: StreamBuilder<DocumentSnapshot>(
  // 第一步:获取当前用户的recipeIDs列表
  stream: Firestore.instance
      .collection('users')
      .document(globals.user.email)
      .collection('colrecipes')
      // 替换为你实际存储recipeIDs的文档ID
      .document('your-recipe-ids-doc-id')
      .snapshots(),
  builder: (context, userSnapshot) {
    if (!userSnapshot.hasData) {
      return Center(child: CircularProgressIndicator());
    }

    // 提取recipeIDs数组,处理空数组情况
    List<String> recipeIDs = List.from(userSnapshot.data['recipeIDs'] ?? []);
    if (recipeIDs.isEmpty) {
      return Center(child: Text('暂无关联食谱'));
    }

    // 第二步:根据ID列表查询主食谱集合
    return StreamBuilder<QuerySnapshot>(
      stream: Firestore.instance
          .collection('colrecipe')
          .where(FieldPath.documentId, whereIn: recipeIDs)
          .snapshots(),
      builder: (context, recipeSnapshot) {
        if (!recipeSnapshot.hasData) {
          return Center(child: CircularProgressIndicator());
        }

        return ListView.builder(
          itemCount: recipeSnapshot.data.documents.length,
          itemBuilder: (context, index) {
            final DocumentSnapshot recipeDoc = recipeSnapshot.data.documents[index];
            
            // 构建食谱卡片(复用原有布局,替换为食谱文档数据)
            return Card(
              margin: const EdgeInsets.all(4.0),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(20),
              ),
              elevation: 20,
              shadowColor: Color.fromARGB(255, 0, 0, 0),
              child: GestureDetector(
                onTap: () => navigateToInfo(recipeDoc),
                onTapDown: (details) => _getTapPosition(details),
                onLongPress: () => _showContextMenu(context),
                child: Container(
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(20.0),
                    child: Column(
                      mainAxisSize: MainAxisSize.max,
                      children: <Widget>[
                        Stack(
                          children: <Widget>[
                            Container(
                              height: MediaQuery(context).size.height * 0.17,
                              decoration: BoxDecoration(
                                image: DecorationImage(
                                  image: NetworkImage(
                                    '${recipeDoc["image"]}?alt=media&token',
                                  ),
                                  fit: BoxFit.cover,
                                ),
                              ),
                            ),
                          ],
                        ),
                        Container(
                          padding: EdgeInsets.symmetric(horizontal: 8, vertical: 6),
                          height: MediaQuery(context).size.height * 0.05,
                          width: MediaQuery(context).size.width,
                          decoration: BoxDecoration(
                            color: Color.fromARGB(146, 205, 204, 204),
                          ),
                          child: Align(
                            alignment: Alignment.centerLeft,
                            child: Text(
                              recipeDoc["recipeName"],
                              style: TextStyle(
                                overflow: TextOverflow.clip,
                                color: Color.fromARGB(255, 51, 44, 25),
                                fontWeight: FontWeight.bold,
                                fontSize: displayWidth(context) * 0.050,
                              ),
                            ),
                          ),
                        ),
                        Container(
                          padding: EdgeInsets.all(5),
                          height: MediaQuery(context).size.height * 0.06,
                          decoration: BoxDecoration(
                            color: Color.fromARGB(255, 98, 91, 94),
                          ),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                            children: [
                              Row(
                                children: [
                                  Transform.scale(
                                    scale: 1.4,
                                    child: Icon(
                                      Icons.room_service,
                                      color: Colors.white,
                                    ),
                                  ),
                                  SizedBox(width: 10),
                                  Text(
                                    recipeDoc["recipeServe"],
                                    style: TextStyle(
                                      fontSize: displayWidth(context) * 0.045,
                                      color: Colors.white,
                                    ),
                                  ),
                                ],
                              ),
                              Row(
                                children: [
                                  Transform.scale(
                                    scale: 1.4,
                                    child: Icon(
                                      Icons.access_time_filled,
                                      color: Colors.white,
                                    ),
                                  ),
                                  SizedBox(width: 10),
                                  Text(
                                    recipeDoc["recipeTimePrepared"],
                                    style: TextStyle(
                                      fontSize: displayWidth(context) * 0.045,
                                      color: Colors.white,
                                    ),
                                  ),
                                ],
                              )
                            ],
                          ),
                        )
                      ],
                    ),
                  ),
                ),
              ),
            );
          },
        );
      },
    );
  },
),

额外说明

  • 请替换代码中的your-recipe-ids-doc-id为实际存储recipeIDs数组的文档ID(如果是自动生成的ID,需确认具体值)
  • 若recipeIDs数量超过50,需将数组拆分为多个子数组(每个最多50个元素),分别查询后合并结果
  • 原代码中if ((recipemodel.recipeName)!.isEmpty)的判断逻辑不合理,直接使用查询到的食谱文档数据即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 00:32:53