Google 数据存储一开始看起来非常好,但后来变得如此令人沮丧,但也许这只是因为我习惯了关系数据库。一般来说,我对数据存储和 nosql 还很陌生,并且做了大量研究,但似乎找不到解决这个问题的方法。
假设我有一个如下所示的 User 类
class User{
@Id
Long id;
String firstName, lastName;
List<Key<User>> friends;
}
我有另一个类,它将对用户所做的事件进行建模
class Event{
Key<User> user;
Date eventTime;
List<Key<User>> receivers;
}
现在我想做的是查询我的 friend 所做的事件。 以通常的关系方式我会说:
select * from Event where user in (select friends from User where id = ?)
以此为起点,我尝试这样做
// Key<User> userKey = ...
User user = ofy.load.type(User.class).key(userKey).first.now;
List<Key<User>> friends = user.getFriends();
ofy.load.type(Event.class).filter("user in", friends).order("-eventTime")list();
但是我听说 30 个子查询的限制使得这种情况不可持续,因为我假设最终有人会有超过 30 个 friend ,更不用说使用“in”子句将保证您无法获得游标来继续加载事件。我做了很多研究并尝试了很多选择,但除了说“为什么是 Google,为什么”之外,还没有找到解决这个问题的好方法。
我考虑过的事情:
- 在事件中添加一个额外字段,该字段是用户好友列表的副本,并在 MVP 上使用单个 equals 来查找事件(非常浪费,因为可能有很多事件。
- 将事件查询一次分成 30 个 friend 的批处理,并以某种方式确定一种方法来确保根据时间从合成游标中持续检索,然后合并它们(问题是太多的边缘情况,使得读取事件非常困难。 )
我非常感谢您提供的任何意见,因为我 100% 没有想法
TL;DR ~ GAE 对子句可以处理的项目数量和 fml 有限制。
最佳答案
您有关系数据库背景,因此非规范化的概念可能有点痛苦 - 我知道这对我来说很痛苦。
现在您有一个表,其中包含所有用户的所有事件。这种方法在关系数据库中效果很好,但由于您提到的原因,在数据存储中却是一场噩梦。
因此,为了解决这个具体问题,您可以按如下方式重组数据:
- 所有用户都有两个时间表。一张是他们自己的帖子,一张是 friend 的帖子。 (公共(public)事务可能有第三个时间表。)
- 发布新事件时,它会写入创建该事件的用户的时间线以及接收用户的所有时间线。 (您可能希望在用户的时间线中添加第三方时间线的引用,以便在用户决定删除事件时知道要删除哪些内容)
现在,每个用户都可以访问完整的时间线、他/她自己的时间线以及由第三方事件创建的时间线。这些时间线很容易查询,并且您根本不需要子选择。
这种方法有缺点:
- 写作成本较高。您必须编写比现在更多的时间表。您可能必须将其放入任务队列中,以便有足够的时间写入所有这些时间线。
- 您使用了更多的存储空间,但存储空间确实很便宜,我猜从长远来看,存储空间会比运行昂贵的查询便宜。
但是,您得到的返回是通过这种非规范化通过简单查询获得闪电般的快速响应。剩下的就是合并 UI 中不同时间线的响应(您可以在服务器端执行此操作,但我会在 UI 中执行此操作)
关于java - 克服谷歌数据存储的 30 个子查询限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40706053/