parse.com'转发'模式太冗长了

jes*_*.tt 43 design-patterns ios parse-platform swift

因此,我的任务是使用Parse在应用程序(iOS,Swift)中实现类似"转推"的功能.

这是在之前被问到的,但这是a)非常高级别的b)我得到了手头的任务 - 我不一定在建筑决策上寻求帮助,但如果看起来我显然错过了什么,我'我乐意接受反馈.

我的应用程序有CAUSES,每个都由USER创建.还有一个带有TO和FROM用户的FOLLOW表.首先,我只是查询CAUSES表,其中发布的USER应该与FOLLOW表中TO用户的objectId(当前用户是FROM用户)匹配.更简洁:

let getFollowedUsersQuery = PFQuery(className: Constants.kParseClassFollowers)
getFollowedUsersQuery.whereKey(Constants.kParseFieldFromUser, equalTo: PFUser.currentUser()!)

let causesQuery = PFQuery(className: Constants.kParseClassCauses)
causesQuery.whereKey(Constants.kParseFieldFromUser, matchesKey: Constants.kParseFieldToUser, inQuery: getFollowedUsersQuery)
causesQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
    if let causes = objects {
        for cause in causes {
          // populate the tableview cells, etc.
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

现在我有来自用户的所有原因,我遵循...这都是非常标准的.

这是它变得棘手的地方.
每个CAUSE也有一个名为SUPPORTERS的Relation.现在我需要构建一种方法来从我不遵循的人那里获得所有CAUSES,但是在他们的支持者列表中有我关注的用户.

我还没有找到一个优雅的解决方案,虽然我正在接近一个"蛮力"的解决方案,它是如此繁琐和冗长,以至于我的程序员大脑中更好的一半像Susan Powter一样尖叫着 ......

这是一个示例:

let retweetQuery = PFQuery(className: Constants.kParseClassCauses)
retweetQuery.orderByDescending(Constants.kParseFieldCreatedAt)
retweetQuery.whereKey(Constants.kParseFieldFromUser, notEqualTo: PFUser.currentUser()!)
retweetQuery.whereKey(Constants.kParseFieldFromUser, doesNotMatchKey: Constants.kParseFieldToUser, inQuery: getFollowedUsersQuery)
retweetQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
    if let causes = objects {
        for cause in causes {
            let supporterRelations = cause.relationForKey(Constants.kParseClassSupporters)
            let supporterQuery = supporterRelations.query()
            supporterQuery.findObjectsInBackgroundWithBlock { (supporters, error) in
                if(error == nil && supporters?.count > 0) {
                    for supporter in supporters! {
                        let user:PFUser = supporter as! PFUser
                        getFollowedUsersQuery.whereKey(Constants.kParseFieldToUser, equalTo: user)
                        getFollowedUsersQuery.whereKey(Constants.kParseFieldFromUser, equalTo: PFUser.currentUser()!)
                        getFollowedUsersQuery.findObjectsInBackgroundWithBlock({ (results, error) -> Void in
                            if(error == nil && results?.count > 0) {
                                for result in results! {
                                    // do stuff
                                }
                            }
                        })
                    }
                }
            }
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

现在,这是纯粹的疯狂,并且令人难以置信的浪费(特别是考虑到Parse如何计算免费等级 - 我觉得如果将其推向生产,这可能会对我的API限制造成很大影响).

已完成两个查询,我完全重做一个,然后对SUPPORTER Relations上的每个原因执行另一个查询,然后对该关系中的每个用户执行另一个查询,看看我是否遵循它们......一旦我有了这些信息,我需要遍历用户支持的原因(由于Parse查询的异步返回,我觉得我根本无法回到父循环中)...我还没有实现,因为我我即将放弃 - 必须有一个更好的方法!

我希望我在这里错过了一个策略......

BHe*_*cks 1

@jesses.co.tt 我很抱歉,如果这太少太晚了,我绝对注意到我在被问到后几个月才回答,但我确实认为这总体上值得回答(也许仍然可以是)对你的价值)。

总的来说,我 100% 同意 Parse 的三重查询 a) 其计费方式(在旧系统中)效率极低,b) 考虑到这一点,即使使用自托管 Parse,这似乎也是错误的方法(从上下文来看,这是自 Parse 现已关闭以来唯一可用的机制,但我认为在提出问题时可能仍然会启动......无论如何......)。我看到有两个解决方案可以以相当干净的方式解决这个问题,假设可以对通用模式/架构进行这些更改。

1) 第一个解决方案是重新架构数据集,本质上是表本身User中每个支持者子集的“外键” User。这样,理论上您可以执行 -> ,而不是从 -> -> 进行操作(Cause默认情况下,您会从用户那里获得他们的支持者,因为它是那里的一个专栏)。要在 中执行此操作,如果我没记错的话,您可以将列设置为具有某种类型的数组作为其值,然后在那里有链接(在 Parse 仪表板中很好地显示)是实际的表对象,但维护此表格中指向该表格的链接列。SupporterUserCauseUserParseobjectSupporterUser

虽然这需要更多的工作write,因为您必须手动执行此操作(手动我的意思是自己编写代码来执行此操作,它应该是自动化的,但在开发方面不会免费发生)。通过这个稍微多一点的前期write操作,您将需要 2 个步骤read而不是 3 个步骤。

2)如果查询速度是一个问题,第二种解决方案是为此类数据使用不同的提供程序。在我的几个项目中,我使用基于套接字的方法来进行这种数据查询查找,并且像PusherFirebase一样思考(两者“全包性”的级别非常不同,Firebase更像是 Parse,但这次来自Google , Pusher是更基本和“DIY”)。

例如,使用Firebase以及此数据集的套接字 + 一个模式,其中Cause表本身具有属于它们的内容的缓存User(并且其中User具有它们的缓存Supporter),这 3 步查找可以有效地1 个带有 2 个参数的查询(我认为这是理想的场景)。我相信这也可以通过 Parse 来实现,但需要对第一个提出的解决方案进行另一步模式重构。

我认为在评论中推荐了与此类似的内容(上述解决方案),但采用了更加未详细说明的格式。我希望这对最初的提问者或某人有所帮助。从理论上讲,正如有人建议的那样,这也可以使用PubNub作为 1 条评论提到的,但它可以轻松地将此模式构建到AWS 或Heroku上托管的PostgreSQL数据库中,并实现与 Parse 完全相同的机制,而无需额外开销。

此外,由于这是参考 Parse,它现在仅作为开源自托管解决方案提供,因此这里有一份迁移到在 AWS 上自行托管 Parse 的指南:链接此处