Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 克服google数据存储的30个子查询限制_Java_Google App Engine_Google Cloud Datastore_Objectify_Nosql - Fatal编程技术网

Java 克服google数据存储的30个子查询限制

Java 克服google数据存储的30个子查询限制,java,google-app-engine,google-cloud-datastore,objectify,nosql,Java,Google App Engine,Google Cloud Datastore,Objectify,Nosql,谷歌数据存储一开始看起来很好,现在变得很令人沮丧,但也许这只是因为我习惯了关系数据库。一般来说,我对数据存储和nosql非常陌生,做了大量的研究,但似乎找不到解决这个问题的方法 假设我有一个如下所示的用户类 class User{ @Id Long id; String firstName, lastName; List<Key<User>> friends; } 以此为出发点,我试着去做 // Key<User> userKey = ..

谷歌数据存储一开始看起来很好,现在变得很令人沮丧,但也许这只是因为我习惯了关系数据库。一般来说,我对数据存储和nosql非常陌生,做了大量的研究,但似乎找不到解决这个问题的方法

假设我有一个如下所示的用户类

class User{
  @Id
  Long id;
  String firstName, lastName; 
  List<Key<User>> friends;
}
以此为出发点,我试着去做

// 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();
//Key userKey=。。。
User User=ofy.load.type(User.class).key(userKey).first.now;
List friends=user.getFriends();
ofy.load.type(Event.class).filter(“用户在”,朋友们).order(“-eventTime”)list();
但我听说这个30个子查询限制使得这个不可持续,因为我假设最终某人将有30多个朋友,更不用说使用“in”子句将保证您无法获得游标来继续加载事件。我做了很多研究,尝试了很多选择,但除了说“为什么谷歌,为什么”之外,还没有找到解决这个问题的好方法

我考虑过的事情:

  • 在事件中添加一个额外的字段,该字段是用户好友列表的副本,并在MVP上使用一个equals来查找事件(因为可能有很多事件,这是非常浪费的)
  • 将事件查询一次分成30个好友的批次,以某种方式确定一种方法,以确保根据时间从合成光标中继续检索,并将它们合并(问题是边缘案例太多,使得读取事件非常困难。)
我真的很感激你能提供的任何意见,因为我100%的想法


TL;DR~GAE对in子句可以处理多少项和fml有限制。

您来自关系数据库背景,因此非规范化的概念可能有点痛苦-我知道这对我来说是很痛苦的

现在,您有一个包含来自所有用户的所有事件的表。这种方法在关系数据库中运行良好,但由于您命名的原因,在数据存储中是一场噩梦

因此,要解决这个具体问题,您可以按如下方式重新构造数据:

  • 所有用户都有两条时间线。一条用于他们自己的帖子,另一条来自朋友的帖子。(可能还有第三条用于公共内容的时间线。)
  • 发布新事件时,它会写入创建它的用户的时间线,以及接收用户的所有时间线。(您可能希望在用户的时间线中添加第三方时间线的引用,以便在用户决定删除事件时知道要删除什么)
现在,每个用户都可以访问完整的时间线,他/她自己的时间线和由第三方事件创建的时间线。这些时间线很容易查询,您根本不需要子选择

这种方法有缺点:

  • 写作成本更高。你必须写比现在更多的时间线。你可能必须把它放在一个任务队列中,以便有足够的时间写所有这些时间线
  • 您使用了更多的存储,但是存储非常便宜,我猜从长远来看,存储将比运行昂贵的查询更便宜

  • 通过这种非规范化,你得到的回报是闪电般的响应和简单的查询。剩下的就是在UI中合并来自不同时间线的响应(你可以在服务器端这样做,但我会在UI中这样做)

    潜在的兴趣:我也看到了这个,但与我的情况无关,因为他/她将所有新闻故事加载到memcache中,因为新闻对所有登录的用户都是全局的。在我的情况下,事件是由用户创建的,但不是所有用户都看到相同的事件,只有他们自己朋友列表中的人的事件。感谢您的后续关注说到这里,我想用光标标出结果,因为可能会有很多事件,将所有事件加载到memcache中似乎是浪费,因为memcache可能会随时消失。我提到这一点主要是为了回答中的建议。是的,我也在查看这一点,我在问题中提到了我是如何考虑将查询拆分为ba的链接中提到的30个tches。这对新闻来源来说可能很好,但问题是边缘案例太多,无法让它可靠地为我工作。如果前90个朋友几年没有活动会怎么样?他们最近的活动通常不是最近的事件。我想展示最近的30个,但最后的结果是你p关于很久以前的事件。要正确处理这些事件是非常困难的,而且加载很多我不想要的事件也是非常浪费的:(是的,你是100%正确的,非规范化的想法是痛苦的,但是这种方法在读取/查询方面肯定是最有效的,我想这是NoSQL类型数据存储的最大好处,并确保在单独的MVP中没有大量重复数据。非常感谢!
    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();