因此,我的任务是使用Parse在应用程序( iOS,Swift )中实现'转推'式功能。
这已在here之前被问过,但这是a)相当高级别的b)我得到了手头的任务 - 我不一定在建筑决策上寻求帮助,不过如果我看来我我显然缺少一些东西,我很乐意接受反馈。
我的应用程序有CAUSES,每个CAUS由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.
}
}
})
现在我已经了解了我所遵循的用户的所有原因......这些都非常标准。
这里变得棘手。
每个CAUSE也有一个名为SUPPORTERS的Relation。
现在我需要构建一种方法来从我不遵循的人那里获得所有CAUSES,但是在他们的支持者列表中有我关注的用户。
我还没有找到一个优雅的解决方案,虽然我正在接近一个“蛮力”的解决方案,而且我的程序员大脑中更好的一半是screaming at me like 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
}
}
})
}
}
}
}
}
})
现在,这是纯粹的疯狂,并且非常浪费(特别是考虑到Parse如何计算免费等级 - 我觉得如果推迟到生产阶段,这可能会对我的API限制造成很大影响)。
已完成两个查询,我完全重做一个,然后在SUPPORTER Relations上为每个原因执行另一个查询,然后在该关系中对每个用户执行另一个查询看看我是否遵循它们......一旦我掌握了这些信息,我就需要遍历用户支持的原因(由于Parse查询的异步返回,我觉得我不能回到父级完全循环)...我还没有实现,因为我要放弃 - 必须有更好的方法!
我希望我在这里错过了一个策略......
答案 0 :(得分:1)
@ jesses.co.tt我很抱歉,如果这太晚太晚了,我肯定会注意到我被问到这几个月之后才会回答,但我认为这一点值得回答(和也许对你来说仍然有价值)。
一般情况下,我100%同意使用Parse进行三重查询是a)按照它的计费方式(在旧系统中)和b)计算方式的效率非常低,看起来像是错误的甚至采用自托管Parse的方法(由于Parse现在已关闭,因此在上下文中这是唯一可用的机制,但我认为当问题被问到时......仍然可能已经上升......无论如何......)。假设可以对一般模式/体系结构进行这些更改,我认为可以以相当干净的方式解决这个问题。
<强> 1)强>
第一种解决方案是重新模式化数据集,基本上是&#34;外键&#34;每个User
的支持者子集都在User
表中。这样,您理论上可以做Cause
- &gt; {{1},而不是从Supporter
- &gt; User
- &gt; Cause
开始(来自用户,默认情况下你会得到他们的支持者,因为它是一个列)。要在 User
中执行此操作,如果我没记错,您可以将列设置为具有特定类型的数组作为其值,然后使用Parse
那里的链接(在Parse仪表板中很好地显示)是实际的object
表对象,但在Supporter
表中保留了该列的链接。
虽然在 User
方面需要更多工作,但由于您必须手动执行此操作(通过手动我的意思是写为了做到这一点,你应该自动编码,但它在开发方面不会免费发生)。通过稍微提前的 write
操作,您可以使用2步 write
而不是3步。
2)如果查询速度有问题,第二种解决方案是为这种数据使用不同的提供程序。在我的几个项目中,我使用基于套接字的方法进行此类数据查询查找,并认为像 Pusher 或 Firebase (两者都非常不同) &strong;&#34;全包性&#34;, Firebase 更像是Parse,但这次来自 Google , {{3} } 有点基础和#34; DIY&#34;)。
例如,使用 Pusher ,以及此数据集的套接字+ read
表本身具有Cause
的缓存的模式s属于它们(并且其中User
具有其User
s的缓存),这3步查找可以实际上是具有2个参数的1个查询(这是我认为理想的情况)。我相信这也可以通过Parse实现,但是需要对第一个提出的解决方案进行另一个模式重构步骤。
我认为在评论中建议采用类似于此的方法(以上解决方案),但采用的方式更为简洁。我希望这有助于原始提问者或某人。理论上,这也可以像推荐的人一样,使用 Firebase 作为提及的1条评论,但它可以轻松地将此架构构建到托管在其上的 PostgreSQL 数据库中AWS或 PubNub 并在没有开销的情况下完成与Parse完全相同的机制。
此外,由于这是对Parse的引用,Parse现在仅作为开源自托管解决方案提供,因此这里有一个指南,用于迁移到在AWS上自己托管Parse:{{3} }