首页 > 解决方案 > Firebase Firestore 使用 ID 引用获取数据,然后获取引用

问题描述

在为这个问题的答案搜索了几个小时后,我在这里找到了 1 篇类似的帖子:但是我试图复制,但我相信语言语法的差异使得翻译变得非常困难。

在我的应用程序中,允许用户发帖,Firsestore 中的帖子结构如下所示:

在此处输入图像描述

creator是也存在于数据库中的用户的用户 ID 。

当我的结构符合 Codable 并且它们将 1 映射到 1 时,我知道如何从 Firestore 获取内容,但我没有经历过在初始获取后必须获取嵌套数据。

问题 通过在我的后端查询帖子,我怎样才能创建驻留在里面的用户对象?

这是我希望创建的 post 对象:

import FirebaseFirestoreSwift

public struct Post: Codable {
    /// The school id
    @DocumentID var id: String?
    /// The name of the school
    public let content: String
    /// The user who made the post
    public var creator: AppUser?
}

我想appUsercreator返回的字段中创建。我应该构建内容然后有某种方式promise.then来获取用户吗?或者我可以同时做这两个吗?

这是我认为我应该做的

    public func fetch(for schoolId: String) -> Promise<[Post]> {
    return Promise { resolver in
        fireStore
            .collection("schools").document(schoolId)
            .collection("posts").getDocuments { (querySnapshot, err) in
                guard let documents = querySnapshot?.documents else {
                  resolver.reject(Errors.firebaseError)
                  return
                }
                
                let posts = documents.compactMap { queryDocumentSnapshot -> Post? in
                  return try? queryDocumentSnapshot.data(as: Post.self)
                }
                
                let postsWithUser: [Post] = posts.map { post in
                    //Fetch User and return an updated struct
                }
                resolver.fulfill(postsWithUser)
            }
    }
}

标签: swiftfirebasegoogle-cloud-firestorepromisekit

解决方案


我解决了!基本上,我们想让第一次 fetch 完成。然后我们遍历每个 post.id 并调用FetchUser()i ,这是我构建的返回函数Promise<User>

func fetchTopLevelPost(for schoolId: String) -> Promise<[Post]> {
    return Promise { resolver in
    fireStore
        .collection("schools").document(schoolId)
        .collection("posts").getDocuments { (querySnapshot, err) in
            guard let documents = querySnapshot?.documents else {
              resolver.reject(Errors.firebaseError)
              return
            }

            let posts = documents.compactMap { queryDocumentSnapshot -> Post? in
              return try? queryDocumentSnapshot.data(as: Post.self)
            }
            resolver.fulfill(posts)
        }
    }
}

func fetchPostUser(for posts: [Post]) -> Promise<[Post]> {
    let allPromise = posts.map{ FetchUser().fetch(for: $0.creatorId) }
    return Promise { resolver in
        when(fulfilled: allPromise).done { users in
            let completePost = zip(users, posts).map(post.init(completeData:))
            resolver.fulfill(completePost)
        }
        .catch { error in
            resolver.reject(Errors.firebaseError)
        }
    }
}

这里是调用点:

public func fetch(for schoolId: String) -> Promise<[Post]> {
    return fetchTopLevelPost(for: schoolId)
        .then { self.fetchPostUser(for: $0) }
}

推荐阅读