parse.com的“retweet”模式太冗长了

所以,我一直负责使用Parse在应用程序( iOS,Swift )中实现类似于“转推”的function。

这已经在这里被问过了 ,但这是一个相当高的水平和b)我手头上的任务 – 我不一定要在build筑决策的帮助,虽然如果看起来我明显缺less的东西,很高兴接受反馈。

我的应用程序有原因,每个用户创build。 还有一个TO和FROM用户的FOLLOW表。 所以开始的时候,我只是简单的查询CAUSES表,其约束条件是发布的USER应该匹配FOLLOW表中的TO用户(其中​​当前用户是FROM用户)的objectId。 更简洁:

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. } } }) 

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

这是棘手的地方。
每个原因也有一个称为支持者的关系。 现在,我需要devise一种方法来获取所有我不遵循的人的原因,但是在他们的支持者名单中有一个我遵循的用户。

我还没有find一个优雅的解决scheme,虽然我正在接近一个'蛮力'之一,它是如此繁琐和冗长,我的程序员的大脑的更好的一半像苏珊·鲍尔特尖叫着我 …

这是一个示例:

 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关系中的每个原因执行另一个查询,然后对该关系中的每个用户执行另一个查询,看看我是否遵循这些查询…一旦获得了这些信息,需要循环通过该用户的支持的原因(因为Parse查询的asynchronous返回,我不觉得我可以回到所有父循环)…我还没有实现,导致我即将扔下毛巾 – 必须有更好的方法!

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

@ jesses.co.tt对不起,如果这太晚了,我肯定注意到,我在回答这个问题后几个月,但我认为这是值得回答一般(也许还可以是价值给你)。

总的来说,我100%的同意,与Parse的三重查询是一个将大规模低效率的方式(在旧系统)和b)考虑到这一点,似乎是错误的方法,即使自我pipe理的parsing(从上下文来看,这是目前唯一可用的机制,因为现在Parse已经closures,但是我认为在问题被问到的时候仍然可能会出现…不pipe…)。 我看到有两种解决scheme可以用相当干净的方式解决这个问题,假设可以对一般的模式/体系结构进行这些更改。

1)第一个解决scheme是重新构造数据集,并且实质上是每个UserUser表本身拥有的支持者子集的“外键”。 这样,不是从Cause – > Supporter – > User ,你理论上可以做Cause – > User (从用户,你会得到他们的支持者默认,因为它会是一个列)。 要在Parse做到这一点,如果我没有记错的话,你可以设置一个列,使其具有一个特定types的数组,因为它的值,然后有object链接(在Parse仪表板中很好地显示)是实际的Supporter表对象,但是在你的User表中维护这个链接到这个表的列。

虽然在write方面还需要更多的工作,但是由于您必须手动执行此操作(通过手动方式,我的意思是自己编写代码来执行此操作,但应该自动执行,但在开发方面不会发生任何问题) 。 有了这个稍微更先进的write操作,然后你有2步read而不是3。

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

例如,对于Firebase ,以及对此数据集的套接字+一个架构表,其中Cause表本身具有User所属的caching(并且在其中User具有其Supporter的caching),则这三步查找可以有效地用2个参数(这是我认为理想的情况)1查询。 我相信这也可以用Parse来实现,但是需要对第一个build议的解决scheme进行模式重构的另一个步骤。

我觉得在评论中推荐了类似这样的东西(上面的两个解决scheme),但是以一个更加没有详细说明的格式。 我希望这有助于最初的提问者或某人。 从理论上讲,也可以像其他人推荐的那样,使用PubNub作为一个注释,但是它可以很容易地将这个模式构build到AWS或Heroku上托pipe的PostgreSQL数据库中,并且完成与Parse完全相同的机制,而不会产生开销。

此外,由于这是参考Parse,现在只提供开源自我托pipe的解决scheme,下面是在AWS上自行迁移到托pipeParse的指南: 此处链接