You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase中如何查询含用户ID的post-saves所属帖子文档

问题分析

你当前的FetchUserSavedPosts方法存在两个核心问题:

  • 错误地直接查询post-saves子集合中的用户ID文档,这些文档仅存储用户ID信息,无法解析为完整的Post对象;
  • Firestore不支持通过子集合的条件直接反向查询父集合文档,必须先定位到包含目标用户ID的post-saves所属的帖子ID,再批量获取对应帖子数据。
修正方案

方案一:适配现有数据结构的查询方式

先遍历所有帖子,筛选出包含当前用户ID的post-saves对应的帖子ID,再批量获取完整帖子数据:

static func fetchUserSavedPosts(uid: String) async throws -> [Post] {
    // 1. 获取所有帖子的基础信息
    let postsSnapshot = try await postsCollection.getDocuments()
    var savedPostIDs: [String] = []
    
    // 2. 逐个检查帖子的post-saves集合是否包含当前用户
    for postDoc in postsSnapshot.documents {
        let saveDoc = try await postDoc.reference.collection("post-saves").document(uid).getDocument()
        if saveDoc.exists {
            savedPostIDs.append(postDoc.documentID)
        }
    }
    
    // 3. 批量获取收藏的完整帖子数据
    if savedPostIDs.isEmpty { return [] }
    let targetPostsSnapshot = try await postsCollection.whereField("id", in: savedPostIDs).getDocuments()
    return try targetPostsSnapshot.documents.compactMap { try $0.data(as: Post.self) }
}

注意:如果帖子数量较大,这种遍历方式会消耗大量读取次数,建议使用下面的优化方案。

方案二:优化数据结构(推荐)

在每个用户的文档下新增saved-posts子集合,用户收藏帖子时同时在两处记录(帖子的post-saves+用户的saved-posts),后续查询效率会大幅提升:

1. 修改收藏帖子的逻辑

static func savePost(_ post: Post) async throws {
    guard let uid = Auth.auth().currentUser?.uid else { return }
    
    // 定义两个需要更新的文档引用
    let postSaveRef = postsCollection.document(post.id).collection("post-saves").document(uid)
    let userSaveRef = Firestore.firestore().collection("users").document(uid).collection("saved-posts").document(post.id)
    
    let userIDData = UserID(id: uid)
    guard let encodedData = try? Firestore.Encoder().encode(userIDData) else { return }
    
    // 事务批量写入,保证操作原子性
    try await Firestore.firestore().runTransaction { transaction in
        transaction.setData(encodedData, forDocument: postSaveRef)
        transaction.setData(["postID": post.id], forDocument: userSaveRef)
    }
}

2. 高效查询用户收藏的帖子

static func fetchUserSavedPosts(uid: String) async throws -> [Post] {
    // 1. 从用户的saved-posts集合获取所有收藏的帖子ID
    let userSavedSnapshot = try await Firestore.firestore().collection("users").document(uid).collection("saved-posts").getDocuments()
    let savedPostIDs = userSavedSnapshot.documents.map { $0.documentID }
    
    // 2. 批量查询完整帖子数据
    if savedPostIDs.isEmpty { return [] }
    let postsSnapshot = try await postsCollection.whereField("id", in: savedPostIDs).getDocuments()
    return try postsSnapshot.documents.compactMap { try $0.data(as: Post.self) }
}
原代码其他问题修正
  • FetchUserSavedPosts中的postsCollection.document()是创建空文档引用,属于无效操作,已在修正方案中移除;
  • savepost方法中的async let _ = try await postRef.setData(encodedPost)无需使用async let,直接调用try await postRef.setData(encodedPost)即可。

内容的提问来源于stack exchange,提问作者Jack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:15:29