Cloud Functions调用Firestore无法查询到数据问题求助
解决Firestore双条件查询返回“No such document!”的问题
嘿,我帮你揪出问题所在啦!你遇到的困境主要来自两个容易踩的Firestore新手坑,咱们一步步拆解解决:
1. 你误解了Firestore查询的不可变性(第一个代码示例的问题)
Firestore的查询对象是不可变的——每次调用.where()、.orderBy()这类方法时,它不会修改原查询,而是返回一个全新的查询实例。你最初的写法:
let selectQuery = admin.firestore().collection("devices"); selectQuery.where("account_id", "==", context.auth.uid); selectQuery.where("device_id", "==", deviceId);
这里selectQuery始终是最初的集合查询,后面两次.where()的结果都没保存,相当于根本没加过滤条件!正确的写法是把每次的查询结果重新赋值,或者用链式调用:
// 方式1:重新赋值 let selectQuery = admin.firestore().collection("devices"); selectQuery = selectQuery.where("account_id", "==", context.auth.uid); selectQuery = selectQuery.where("device_id", "==", deviceId); // 方式2:更简洁的链式调用 const selectQuery = admin.firestore().collection("devices") .where("account_id", "==", context.auth.uid) .where("device_id", "==", deviceId);
2. 混淆了QuerySnapshot和DocumentSnapshot(核心问题)
当你对查询调用.get()时,返回的是QuerySnapshot(哪怕只匹配一个文档),而不是单个DocumentSnapshot。QuerySnapshot没有.exists属性,你用doc.exists判断自然会得到false,这就是为什么一直打印“No such document!”。
正确的判断逻辑是检查查询结果是否为空:
.get().then(function(querySnapshot) { if (!querySnapshot.empty) { // 因为你的条件应该唯一匹配一个文档,直接取第一个结果 const targetDoc = querySnapshot.docs[0]; console.log("Document data:", targetDoc.data()); } else { console.log("No such document!"); } return "asd"; })
额外验证建议
- 先确认
context.auth.uid和deviceId的取值和Firestore里的字段完全一致(注意大小写、空格、特殊字符,比如你提供的UIDwFK2JVghw8XjVGqlEE0Uj09irGK2和552cbe50f935de7a,要确保数据库里的account_id、device_id字段值和它们丝毫不差)。 - 可以先在Firestore控制台手动用这两个条件查询,看看能不能找到文档,排除数据本身的问题。
修正后的完整代码
exports.authDevice = functions.https.onCall((data, context) => { if (!context.auth) { throw new functions.https.HttpsError('failed-precondition', 'The function must be called while authenticated.'); } const deviceName = data.device_name; const deviceId = data.device_id; const isQR = data.is_qr; const uid = context.auth.uid; console.log("DEVICE NAME: " + deviceName); console.log("DEVICE ID: " + deviceId); console.log("is QR: " + isQR); console.log("UID: " + uid); // 注意要返回Promise,否则Cloud Functions会提前终止异步操作 return admin.firestore().collection("devices") .where("account_id", "==", uid) .where("device_id", "==", deviceId) .get() .then(function(querySnapshot) { if (!querySnapshot.empty) { const targetDoc = querySnapshot.docs[0]; console.log("Document data:", targetDoc.data()); return { success: true, data: targetDoc.data() }; } else { console.log("No such document!"); return { success: false, message: "No such document!" }; } }) .catch(function(error) { console.log("Error getting document:", error); throw new functions.https.HttpsError('internal', 'Failed to fetch device data', error); }); });
内容的提问来源于stack exchange,提问作者user93466
相关产品推荐
相关产品推荐

