【问题标题】:Firebase Firestore: How to implement a "likes" system?Firebase Firestore:如何实现“点赞”系统?
【发布时间】:2020-02-27 20:09:56
【问题描述】:

当 currentUser 点击likeButton 时,我会运行一个事务,但我想检查用户是否已经喜欢该帖子。如果用户已经喜欢了帖子,我想减少likeCounter并改变likeButton的外观,否则我想增加它。

我的 Firestore 数据库使用了 collection.document.collection.document.... 的东西:

"posts":
    - "post1":
        - uid: user1
        - likeCount: 2
        - caption: "caption1"
        - "likes":
            - "user1":
                - value: true
            - "user2":
                - value: true
    - "post2":
        - uid: user1
        - likeCount: 1
        - caption: "caption2"
        - "likes":
            - "user1":
                - value: true
            - "user4":
                - value: true
    - "post3":
        - uid: user2
        - likeCount: 3
        - caption: "caption3"
        - "likes":
            - "user1":
                - value: true
            - "user3":
                - value: true
            - "user4":
                - value: true

这是我的 incrementLikes() 函数,每当用户点击 likeButton 时都会调用该函数

func incrementLikes() {
    let ref = Api.Post.REF_POSTS.document(self.post!.id!)

    Firestore.firestore().runTransaction({ (transaction, errorPointer) -> Any? in
        let sfDocument: DocumentSnapshot
        do {
            try sfDocument = transaction.getDocument(ref)
        } catch let fetchError as NSError {
            errorPointer?.pointee = fetchError
            return nil
        }

        guard let oldLikes = sfDocument.data()?["likeCount"] as? Int else {
            let error = NSError(
                domain: "AppErrorDomain",
                code: -1,
                userInfo: [
                    NSLocalizedDescriptionKey: "Unable to retrieve likes from snapshot \(sfDocument)"
                ]
            )
            errorPointer?.pointee = error
            return nil
        }
        transaction.updateData(["likeCount": oldLikes - 1], forDocument: ref)
        if let currentUser = Auth.auth().currentUser {
            ref.collection(K.likesCollection).document(currentUser.uid).delete()
        }
        DispatchQueue.main.async {
            self.likeImageView.image = UIImage(systemName: K.heart)
            self.likeImageView.tintColor = UIColor.black
        }
        return nil
    }) { (object, error) in
        if let error = error {
            print("Transaction failed: \(error)")
        } else {
            print("Transaction successfully committed!")
        }
    }
}

我想知道我的数据库是否以最可扩展的正确方式构建,以及我应该在哪里以及如何放置观察者以查看用户是否已经喜欢该帖子。

【问题讨论】:

  • 这个问题有点不清楚。如果您想检查用户是否喜欢该帖子 - 这可以通过观察SingleEvent 用户喜欢该键的帖子来完成,如果它存在则减少帖子的likeCounter。您实际上甚至不需要查询,因为您知道帖子 ID 以查看它是否存在。入门指南Read Data Once 中介绍了读取数据。如果这不是你要问的,你能澄清一下这个问题吗?
  • 感谢您的回答,但我使用的是 Firestore 而不是实时数据库,因此无法使用 observingSingleEvent 方法,有什么方法可以使用 Firestore 实现它吗?
  • 另外,我应该将观察者放在 runTransaction 方法的哪个位置?再次感谢
  • 哎呀,对不起。其实Firestore中也有获取一次数据的概念见Get Data Once,用法类似。获取文档,如果它存在(document.exists)然后减少likeCounter。此外,您不需要在 Firebase 闭包中使用此 DispatchQueue.main.async,因为 UI 调用在主线程上运行,而网络调用在后台线程上自动运行。

标签: ios swift firebase google-cloud-firestore transactions


【解决方案1】:

在考虑一种扩展方式时,我意识到与其为每个帖子加载所有用户喜欢的内容,不如保存并加载用户喜欢的所有帖子 ID。一个帖子可以有 50k、500k 或 500 万个赞,但一个用户可能有最多 1-5k 个赞。您可以在用户下创建一个“喜欢的帖子”集合,您可能可以在一次阅读中获取用户喜欢的所有帖子,这会更快。

【讨论】:

    【解决方案2】:

    当我使用 Firebase 创建一个社交媒体平台时,使用帖子中的儿童数量更容易获得likeCounter。然后,在检查 likeButton 是否应该显示它是否被喜欢时,只需查看他们的 userId 是否在孩子中。

    我发现这个更好的原因是:

    1. 如果 Internet 不安全,计数器很容易出现错误。

    2. 当我想让用户看到还有谁喜欢这篇文章时,无论如何我都必须创建第二个分支。它实际上节省了重复代码。

    我是这样设置的:

    "posts":
        - "post1":
            - uid: user1
            - caption: "caption1"
                     -"LikedBy": 
                         -LikedBy:"user1"
                         -LikedBy:"user3"
    
    // we added "LikedBy": so that instead of using likeCounter, 
    //you could get the count from it's children. 
    //To see if it's already liked by the user,
    // find the name in this branch. If user1 finds his name in the children, 
    //it'll return true. That means he's liked it.
    
    
        - "post2":
            - uid: user1
            - caption: "caption2"
                   -"LikedBy":
                         -LikedBy:"user1"
                         -LikedBy:"user3"
        - "post3":
            - uid: user2
            - caption: "caption3"
                  -"LikedBy":
                         -LikedBy:"user1"
                         -LikedBy:"user2"
                         -LikedBy:"user3"
    
    
    
    // as you can see this is no longer used
    
    "likesPerUser":
            - "user1":
    
            - "user2":
    
            - "user3":
    

    【讨论】:

    • 但是如果您想查看用户是否喜欢帖子,您将加载所有用户喜欢的帖子?
    • 啊,是的。我没有想到这一点,因为我的应用程序非常小。我想这毕竟不是最好的方法。
    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 2015-03-16
    相关资源
    最近更新 更多