ios - 如何获取当前登录用户关注的用户帖子

标签 ios swift firebase google-cloud-firestore

我正在使用 Cloud Firestore 来存储我的应用数据。我在从当前登录用户关注的用户那里获取帖子时遇到问题。我按这样的数据库结构

Firestore-root
   |
   --- users (collection)
   |     |
   |     --- uid (documents)
   |          |
   |          --- name: "User Name"
   |          |
   |          --- email: "email@email.com"
   |
   --- following (collection)
   |      |
   |      --- uid (document)
   |           |
   |           --- userFollowing (collection)
   |                 |
   |                 --- uid (documents)
   |                 |
   |                 --- uid (documents)
   |
   --- posts (collection)
         |
         ------- postId (document)
                    |
                    |
                    --- uid: user
                    |
                    --- timestamp: 1570044062.261539
                    |
                    --- status: "status"

当我获取供稿的帖子时。我将查询返回的数据分成批处理,并按时间戳对批处理进行排序。每个批处理有 10 个帖子,但是这些批处理不包含当前登录用户关注的用户的帖子。它读取当前存储在数据库中的所有帖子,无论谁在关注谁

postsQuery = db.collection("posts").order(by: "timestamp", descending: true).limit(to: 10)

当用户登录并加载他们的 feed 时,fetchFirstBatch() 函数会发送前 10 个帖子的请求

private func fetchFirstBatch() {
        self.displaySpinner(onView: self.view)
        print("Fetching first batch")
        postsQuery.getDocuments { (snapshot, error) in
            guard let snapshot = snapshot else {
                print("Error retrieving batch: \(error.debugDescription)")
                return
            }

            guard let lastSnapshot = snapshot.documents.last else {
                return
            }

            for document in snapshot.documents {
                let data = document.data()
                let postType = data["post type"] as? String ?? ""

                if postType == PostType.Status.type {
                    let status = data["status"] as? String ?? ""
                    let timestamp = data["timestamp"] as? Double ?? 0
                    let uid = data["user id"] as? String ?? ""
                    let username = data["username"] as? String ?? ""

                    self.posts.append(Post(status: status, timestamp: timestamp, postType: PostType.Status, userId: uid, username: username))
                }
                self.tableView.insertRows(at: [IndexPath(row: self.posts.count - 1, section: 0)], with: .automatic)
            }

            self.lastSnapshot = lastSnapshot

            DispatchQueue.main.async {
                self.tableView.reloadData()
                self.removeSpinner()
            }
        }
    }

一旦用户滚动到包含所有帖子的 TableView 底部,fetchNextBatch() 函数将获取下一批帖子

private func fetchNextBatch() {
        print("Fetching next batch")
        fetchingBatch = true

        postsQuery.start(afterDocument: lastSnapshot).getDocuments { (snapshot, error) in
            guard let snapshot = snapshot else {
                print("Error retrieving batch: \(error.debugDescription)")
                return
            }

            guard let lastSnapshot = snapshot.documents.last else {
                print("No more batches to fetch")
                self.fetchingBatch = false
                return
            }

            for document in snapshot.documents {
                let data = document.data()
                let postType = data["post type"] as? String ?? ""

                if postType == PostType.Status.type {
                    let status = data["status"] as? String ?? ""
                    let timestamp = data["timestamp"] as? Double ?? 0
                    let uid = data["user id"] as? String ?? ""
                    let username = data["username"] as? String ?? ""

                    self.posts.append(Post(status: status, timestamp: timestamp, postType: PostType.Status, userId: uid, username: username))
                }
                self.tableView.insertRows(at: [IndexPath(row: self.posts.count - 1, section: 0)], with: .automatic)
            }

            self.lastSnapshot = lastSnapshot

            DispatchQueue.main.async {
                self.tableView.reloadData()
            }

            self.fetchingBatch = false
        }
    }

如何附加当前登录用户关注的用户的所有帖子,同时对每批获取的数据进行分页?我尝试复制的提要结构是 Instagram 提要。

最佳答案

最好将您的问题分解成更小的部分,因为您提出的问题是您及其实现的一个完整功能。

我不明白为什么要将以下集合与用户集合分开并将它们放在数据模型的顶层,因为基本上在那里,您已经创建了另一个层来将 userFollowing 子集合添加到用户文档。您可以将 userFollowing 重新定位到下一级用户文档。还是那句话,这取决于你是想存储用户(用户关注的人)的全部数据,还是用他们自己的 uid 填充他们的文档。

但是查看数据模型的当前状态,类似于下面的代码可以帮助您解决这个问题:

const arrayOfPeopleWhichUserFollows = await db.collection('following').doc(userId).collection('userFollowing').get()
      .then(querySnapshot => {
        return  querySnapshot.docs.map((doc) => {
          return doc.data().uid;
        });
      });


    // you have to measure the size of arrayOfPeopleWhichUserFollows to check whether it exceeds the limitation of 10
    // for using in the "where in" query from firestore
    // then breaks the array into a smaller piece, as small as 10 items per array and the repeat the below part for all the
    // fragmented arrays and append all the results into a single variable

    const firstPosts = await db.collection('posts')
      .where('uid', 'in', fragmentedArrayOfPeopleWhichUserFollows)
      .orderBy('timestamp', 'desc').limit(10);

    const posts = await firstPosts.get()
      .then(querySnapshot => {
        const lastVisible = querySnapshot.docs[querySnapshot.docs.length - 1];
        return querySnapshot.docs.map((post) => {
          return post.data();
        });
        const nextPosts = db.collection('posts')
          .where('uid', 'in', fragmentedArrayOfPeopleWhichUserFollows)
          .orderBy('timestamp', 'desc')
          .startAfter(lastVisible)
          .limit(10)
      });

考虑阅读这些链接:

how to write queries in firestore

how to paginate your data while querying from firebase

how to Manage indexes in Cloud Firestore

关于ios - 如何获取当前登录用户关注的用户帖子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59068295/

相关文章:

ios - 终止 iOS 应用程序

ios - 如何使 UILabel 可点击?

dynamic - swift : Parse subclass dynamic var dont get included when retrieving object

Firebase 云消息统计 API

iOS:带有 1 个标签和 3 个按钮的简单自动布局

ios - 如何使用 NEPacketTunnelProvider 获取完整的 URL?

ios - .animationImages API Cocos 2D?

iphone - 我可以在 iOS 通知中显示图像吗?

具有重写功能的 Firebase 托管不会设置 session cookie

node.js - 无法执行 "sudo npm install --save firebase-admin"