在Next.js中如何通过Slug字段从Firebase获取单篇文档?
问题
我尝试使用getDoc方法从Firebase获取仅一篇文档,但该方法需要传入文档的id而非slug字段。目前我通过getDocs函数并传入slug作为查询条件来获取单篇文档,代码如下:
export async function getStaticPaths() { const challenges = await getDocuments("challenges") const paths = challenges.map((doc) => { return { params: { slug: doc.slug }, } }) return { paths, fallback: false, } } export async function getStaticProps({ params }) { const slug = params.slug const data = await getDocuments("challenges", ["slug", "==", slug]) const challenge = data[0] return { props: { challenge }, } }
getDocuments函数代码如下:
export const getDocuments = async (c, q = null, l) => { const queryConstraints = [] if (q !== null) queryConstraints.push(where(...q)) if (l !== null) queryConstraints.push(limit(l)) const ref = collection(db, c) const docsRef = query(ref, orderBy("createdAt", "desc"), ...queryConstraints) const documents = (await getDocs(docsRef)).docs.map(postToJSON) return documents }
我有两个问题:
- 是否有更优的单文档获取方式?
- 计费是按单篇文档还是challenges集合中的所有文档计算?
回答
1. 更优的单文档获取方式
可以从这几个方向优化:
- 给slug字段加唯一索引:在Firebase控制台的Firestore页面,给
challenges集合的slug字段创建单字段索引(如果查询提示需要复合索引,再补充创建包含createdAt和slug的复合索引)。这能确保slug唯一,避免多文档匹配的情况,同时提升查询性能。 - 添加
limit(1)约束:查询slug时传入limit(1),让Firestore只返回第一个匹配的文档,减少数据传输量,同时明确查询意图。修改getStaticProps的调用:const data = await getDocuments("challenges", ["slug", "==", slug], 1) - 封装专属单文档查询函数:单独写一个函数简化调用逻辑,比如:
在export async function getDocumentBySlug(collectionName, slug) { const ref = collection(db, collectionName) const queryRef = query(ref, where("slug", "==", slug), limit(1)) const snapshot = await getDocs(queryRef) return snapshot.docs.length > 0 ? postToJSON(snapshot.docs[0]) : null }getStaticProps里直接调用:const challenge = await getDocumentBySlug("challenges", params.slug)
2. Firestore计费规则
Firestore的读取计费是按实际返回的文档数量计算的:
getStaticProps中的查询:只要slug是唯一的,查询只会返回1篇文档,按1次读取操作计费;如果存在多个相同slug的文档,会按匹配到的文档总数计费。getStaticPaths中的getDocuments("challenges"):这个调用会读取challenges集合下的所有文档,计费数量等于集合内的文档总数。
内容的提问来源于stack exchange,提问作者r121
相关产品推荐
相关产品推荐

