手动命名数字ID时Firestore无法获取最后添加文档名称求助
问题分析与解决
问题原因
你当前的查询是按文档字段id排序,但你只是把文档ID命名为数字(1、2、3...),文档本身并没有存储id字段。Firestore的orderBy('id')只会查找文档内部的字段,不会识别文档ID作为排序依据,所以查询结果为空,导致lastDocName始终是初始空字符串,后续转数字递增自然得到NaN。而使用自动生成ID时正常,大概率是你当时给文档添加了id字段,或者自动ID的字符串排序刚好符合预期,但这不是正确的做法。
解决方案
1. 按文档ID排序查询
要基于文档ID排序,需要使用FieldPath.documentId()来指定排序依据,修改查询代码如下:
// Get a reference to the collection const collectionRef = collection(db, 'questions'); // 改用文档ID作为排序字段 const q = query(collectionRef, orderBy(firebase.firestore.FieldPath.documentId(), 'desc'), limit(1)); const querySnapshot = await getDocs(q); let lastDocName = ''; querySnapshot.forEach(doc => { lastDocName = doc.id; }); console.log("Last Doc called: ", lastDocName);
2. 安全生成下一个ID
拿到lastDocName后,要先判断是否为空,再转成数字递增,避免NaN:
// 生成下一个ID const nextId = lastDocName ? parseInt(lastDocName, 10) + 1 : 1; console.log("Next ID: ", nextId);
额外建议
如果需要严格的自增ID,手动维护文档ID存在并发风险(比如多个用户同时查询最后一个ID并生成新ID,会导致重复)。更可靠的方式是使用Firestore的计数器模式:单独维护一个计数器文档,每次新增文档时通过事务递增计数器,再用这个值作为文档ID。示例代码如下:
// 事务递增计数器并获取新ID async function getNextQuestionId() { const counterRef = doc(db, 'counters', 'questionId'); const transactionResult = await runTransaction(db, async (transaction) => { const counterDoc = await transaction.get(counterRef); if (!counterDoc.exists()) { await transaction.set(counterRef, { currentId: 1 }); return 1; } const currentId = counterDoc.data().currentId; const nextId = currentId + 1; await transaction.update(counterRef, { currentId: nextId }); return nextId; }); return transactionResult; } // 使用示例 const newQuestionId = await getNextQuestionId(); const newDocRef = doc(db, 'questions', newQuestionId.toString()); await setDoc(newDocRef, { /* 你的文档数据 */ });
内容的提问来源于stack exchange,提问作者Ishimwe etienne
相关产品推荐
相关产品推荐

