Firebase Firestore 使用 ID 引用获取数据然后获取引用
Firebase Firestore fetching data with an ID reference then fetching the reference
在为这个问题的答案搜索了几个小时之后,我找到了 1 个 post 相似 :但是我试图复制,但我相信语言语法的差异造成了很难翻译。
在我的应用程序中,允许用户创建 posts,Firsestore 中 post 的结构如下所示:
creator
是也存在于数据库中的用户的用户 ID。
我知道当我的结构符合 Codable 并且它们将 1 映射到 1 时如何从 Firestore 中获取内容,但我没有经历过在初始获取后必须获取嵌套数据的情况。
问题
通过向我的后端查询 posts,我还如何创建位于其中的用户对象?
这是我期望创建的 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?
}
我想从返回的 creator
字段创建 appUser
。我应该构建内容然后使用某种 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)
}
}
}
我解决了!基本上,我们想让第一次获取完成。然后我们遍历每个 post.id 并调用 FetchUser()
i 这是我构建的函数 returns 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: [=10=].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: [=11=]) }
}
在为这个问题的答案搜索了几个小时之后,我找到了 1 个 post 相似
在我的应用程序中,允许用户创建 posts,Firsestore 中 post 的结构如下所示:
creator
是也存在于数据库中的用户的用户 ID。
我知道当我的结构符合 Codable 并且它们将 1 映射到 1 时如何从 Firestore 中获取内容,但我没有经历过在初始获取后必须获取嵌套数据的情况。
问题 通过向我的后端查询 posts,我还如何创建位于其中的用户对象?
这是我期望创建的 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?
}
我想从返回的 creator
字段创建 appUser
。我应该构建内容然后使用某种 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)
}
}
}
我解决了!基本上,我们想让第一次获取完成。然后我们遍历每个 post.id 并调用 FetchUser()
i 这是我构建的函数 returns 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: [=10=].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: [=11=]) }
}