我正在处理移动应用的通知Feed,并正在寻找有关问题的帮助。
该应用程序是一个类似Twitter / Facebook的应用程序,用户可以在其中发布状态,其他用户可以喜欢,评论或订阅它们。
我希望在我的应用中有一件事就是拥有一个通知Feed,用户可以在其中看到谁喜欢/评论他们的帖子或订阅了他们。
我已经想到这个系统的第一部分,当用户喜欢/ comments / subscribes时,Notification
实体将被写入数据存储区,其中包含有关该事件的详细信息。要向用户显示Notification
,我要做的就是查询该用户的所有Notification
,按日期创建的desc排序,我们有一个很好的小馈送其他用户对特定用户帐户采取的操作。
我遇到的问题是当有人不喜欢帖子,取消订阅或删除评论时该怎么做。目前,如果我要查询该特定通知,则可能由于最终的一致性而不会从数据存储区返回任何内容。我们可以想象有人喜欢,然后立即不喜欢一个帖子(b / c谁没有做过?= P)。查询Notification
的查询可能会返回null并且在调用ofy().delete().entity(notification).now();
时不会删除任何内容现在用户在他们的Feed中有通知说Sally喜欢他的帖子,而实际上她喜欢然后很快就不喜欢它!
整个系统中的一个扳手是我无法通过Key<Notification>
删除,因为我在尝试删除时无法真正了解id
的{{1}}它。
我正在尝试的潜在解决方案是不删除任何Notification
。相反,我总是会写Notification
并简单地指出通知是正面的还是负面的。然后在我的查询中向特定用户显示通知,我可以某种方式只显示总和为Notification
的。这样可以节省一些数据存储空间,因为删除实体很昂贵。
答案 0 :(得分:1)
我之前有三种主要方法可以解决这个问题:
确定性密钥
例如
{user-Id} - {post-id} - {likes-by} for likes
{user-id} - {post-id} - {comment-by} - {comment-index}征求意见
这对于您定义的问题的大多数基本用例都有效,但是您可以找出一些毛茸茸的边缘情况(比如在编辑和删除注释时管理注释的索引)。这将允许按键
获取和删除这里的想法是在事务中一次创建多个实体,但要确保它们具有相关的密钥。例如,当有人对Feed项进行注释时,创建一个Comment实体,然后创建一个具有相同ID的CommentedOn实体,但使其具有该评论者用户的父键。
然后,您可以对CommentedOn进行强一致性查询,并使用相同的id在Comment上按键获取。您也可以只存储一个密钥,而不是具有匹配的ID,如果这太难了。每次执行此操作时,在实践中使用匹配的ID都会更容易。
这种方法的主要限制是您可以自己从实体中有效地创建索引,虽然这可以为您提供需要它们的强一致性查询,但事务性写入的吞吐量限制可能变得更难理解。您还需要仔细管理状态更改(如删除)。
假设Notification对象只是向用户显示发生了某些事情但链接到另一个实体的实际数据,您可以在该实体上存储状态标志(已删除,隐藏,私有等)。然后列出您的通知将是加载实体服务器端并在代码中过滤(或可能是后续过滤的查询)。
在一天结束时,解决方案的复杂性应该反映问题的复杂性。我将从方法3开始,然后在理解更全面的需求时迁移到方法2。这是一种更强大,更灵活的方法,但XG交易限制的复杂性将会发挥作用 - 但最终像这样的分布式馈送是一个难题。
答案 1 :(得分:0)
我最终做的以及对我的特定模型有用的是,在创建Notification
实体之前,我首先要为它分配和ID:
// Allocate an ID for a Notification
final Key<Notification> notificationKey = factory().allocateId(Notification.class);
final Long notificationId = notificationKey.getId();
然后在创建我的Like
或Follow
实体时,我会设置属性Like.notificationId = notificationId;
或Follow.notificationId = notificationId;
然后我会保存两个实体。
稍后,当我想要删除Like
或Follow
我可以同时获取Notification
的ID时,请加载Notification
key(这与此非常一致),并将其删除。
另一种方法可以帮助某人= D