Flutter Firebase:嵌套集合文档更新及文档ID获取问题
问题解答
一、现有代码的问题
你的代码语法本身没有语法错误,但逻辑存在明显问题,会导致功能异常:
- 你给
exercises集合的文档使用了和user_workouts相同的docId,这会导致每次添加动作都会覆盖同一个文档,无法创建多条训练动作条目。 - 使用
update()方法要求目标文档必须已存在,如果是第一次给该训练计划添加动作,这个文档不存在,会直接抛出错误,无法完成添加。
正确的做法是:添加新训练动作时,要么让Firebase自动生成新的文档ID,要么自定义唯一ID,然后用set()或add()方法创建新文档,而非update()。
二、如何获取/生成两个集合对应的文档ID
1. 获取user_workouts的文档ID(指定训练计划的ID)
这个ID是用户创建训练计划时生成的,你需要在创建环节就把它保存下来(比如存在页面状态、全局状态或本地存储中):
- 创建训练计划的示例代码:
// 创建新训练计划,Firebase自动生成唯一ID final workoutDocRef = FirebaseFirestore.instance.collection('user_workouts').doc(); final workoutId = workoutDocRef.id; // 提取训练计划ID // 保存训练计划的基础数据 await workoutDocRef.set({ 'workoutName': '胸部专项训练', 'createTime': DateTime.now(), // 其他训练计划相关字段 }); // 把workoutId存储起来,比如传递到添加动作的页面,或者存在页面state里
后续添加动作时,直接调用这个保存好的workoutId即可,不用硬编码。
2. 生成exercises集合的文档ID(训练动作的ID)
有两种常用方式:
方式一:让Firebase自动生成唯一ID(推荐)
使用add()方法,Firebase会自动生成新文档ID并创建文档:
// 传入之前保存的训练计划ID addExercise(String workoutId) { if (exerciseNameController.text.trim().isEmpty) { print('请输入动作名称'); return; } FirebaseFirestore.instance .collection('user_workouts') .doc(workoutId) .collection('exercises') .add({ 'Exercise': exerciseNameController.text.trim(), 'Reps': repsController.text.trim(), 'Sets': setsController.text.trim() }) .then((docRef) { print('动作添加成功,动作ID: ${docRef.id}'); // 可在此清空输入框 exerciseNameController.clear(); repsController.clear(); setsController.clear(); }) .catchError((error) => print('添加失败: $error')); }
方式二:自定义文档ID
如果你想自己指定动作的唯一ID(比如用动作名称+时间戳),可以用doc()传入自定义ID,再用set()创建文档:
addExercise(String workoutId) { if (exerciseNameController.text.trim().isEmpty) { print('请输入动作名称'); return; } // 自定义唯一ID,避免重复 final exerciseId = '${exerciseNameController.text}_${DateTime.now().millisecondsSinceEpoch}'; FirebaseFirestore.instance .collection('user_workouts') .doc(workoutId) .collection('exercises') .doc(exerciseId) .set({ 'Exercise': exerciseNameController.text.trim(), 'Reps': repsController.text.trim(), 'Sets': setsController.text.trim() }) .then((_) => print('动作添加成功')) .catchError((error) => print('添加失败: $error')); }
内容的提问来源于stack exchange,提问作者Jeff Barra
相关产品推荐
相关产品推荐

