FlutterFire Firestore查询问题:无结果时返回值及代码优化
1. 基础疑问解答
首先得明确:result.exists这个属性是**针对单个文档快照(DocumentSnapshot)**的,它的作用是判断这个快照对应的Firestore文档是否真的存在(比如你通过collection('users').doc('some-id').get()获取的单个文档快照,用exists来确认这个ID的文档有没有)。
当你执行一个查询(比如where(...).get()),如果没有匹配结果,返回的QuerySnapshot里的docs是一个空数组,根本不会进入forEach循环,所以你不会看到任何result.exists的输出——因为连可遍历的结果都没有,自然不会触发这个判断。
2. 实际代码问题修复
你的代码现在只处理了“查询到文档”的情况,完全没考虑“查询结果为空”的场景,所以当bizCode不存在时,forEach根本不执行,也就没有任何输出。
修改思路很简单:先检查查询结果的文档列表是否为空,再分别处理两种情况。如果你的bizCode是唯一标识(每个用户的bizCode不重复),其实不需要遍历所有文档,直接判断docs.isNotEmpty就够了,代码会更简洁:
await FirebaseFirestore.instance .collection("users") .where('bizCode', isEqualTo: 'abcdef') .get() .then((querySnapshot) { if (querySnapshot.docs.isNotEmpty) { // 这里可以取第一个文档,因为bizCode唯一的话最多一个结果 final result = querySnapshot.docs.first; print(result.exists); // 这里肯定是true,因为能出现在docs里的都是存在的文档 print('code exists'); } else { // 没有匹配结果的情况 print('no such code'); } });
如果你的bizCode可能重复(多个用户有同一个bizCode),需要遍历所有匹配文档的话,也可以先判断空数组的情况:
await FirebaseFirestore.instance .collection("users") .where('bizCode', isEqualTo: 'abcdef') .get() .then((querySnapshot) { if (querySnapshot.docs.isEmpty) { print('no such code'); } else { querySnapshot.docs.forEach((result) { print(result.exists); // 同样,这里都是true print('code exists'); }); } });
补充一句:为什么result.exists在遍历的时候总是true?因为QuerySnapshot里的docs只会包含那些在Firestore中实际存在的文档的快照,不存在的文档不会被包含进来,所以遍历的时候每个result.exists都是true,这个判断其实可以省略,直接用docs.isNotEmpty来判断是否有匹配结果就够了。
内容的提问来源于stack exchange,提问作者Shaun Wu

