Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.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
Google app engine GAE/J中的数据库设计:关系建模与实体属性值_Google App Engine_Google Cloud Datastore_Data Modeling - Fatal编程技术网

Google app engine GAE/J中的数据库设计:关系建模与实体属性值

Google app engine GAE/J中的数据库设计:关系建模与实体属性值,google-app-engine,google-cloud-datastore,data-modeling,Google App Engine,Google Cloud Datastore,Data Modeling,假设您计划创建一个运行在GAE/Java上的社交网络,其中每个用户都有一组属性(即年龄、当前城镇、兴趣) 备选方案1:经典方法-将用户id和每个属性作为“行” 备选方案2:实体atributte值(EAV) 您认为每个选项有哪些优点/缺点?我主要关注的是: 对多条件搜索有什么影响(即“给我那些居住在纽约且喜欢书籍的45岁以下用户”) 它可能有什么GAE/J含义?(即索引、数据存储大小…) 如果要检索“喜欢书籍的用户”,如何使用多个值(例如“兴趣”)对属性建模 我认为第二种选择更灵活,可能更容易实

假设您计划创建一个运行在GAE/Java上的社交网络,其中每个用户都有一组属性(即年龄、当前城镇、兴趣)

备选方案1:经典方法-将用户id和每个属性作为“行”

备选方案2:实体atributte值(EAV)

您认为每个选项有哪些优点/缺点?我主要关注的是:

  • 对多条件搜索有什么影响(即“给我那些居住在纽约且喜欢书籍的45岁以下用户”)
  • 它可能有什么GAE/J含义?(即索引、数据存储大小…)
  • 如果要检索“喜欢书籍的用户”,如何使用多个值(例如“兴趣”)对属性建模
  • 我认为第二种选择更灵活,可能更容易实现,但我想知道其他有经验的开发人员的想法


    谢谢。

    你看过谷歌I/O 2009吗?这段视频的音质很差,但它涵盖了你的主题。他谈到了列表属性和合并联接及其局限性。

    如果EAV的灵活性对你的应用程序至关重要,那么就使用它,否则就不要使用,因为它在查询时会有陷阱

    将返回所有拥有权益账簿的实体:

    final Iterator<EAV> eavs = Iterators.transform(
        datastoreService.prepare(
            new Query(EAV.class.getSimpleName()).addFilter("a",
                FilterOperator.EQUAL, "interests").addFilter(
                "v", FilterOperator.EQUAL, "books"))
            .asIterator(), new Function<Entity, EAV>() {
          @Override
          public EAV apply(final Entity input) {
            return new EAV(input);
          }
        });
    while (eavs.hasNext()) {
      logger.debug("eav: " + eavs.next());
    }
    
    结果并不令人惊讶,因为大表中的查询甚至没有接近SQL的灵活性(例如,没有连接)。工作解决方案可能是多个查询,并手动组合和解析它们的结果

    OTOH的“经典方法”很简单:

    final Iterator<Person> persons = Iterators.transform(
        datastoreService
            .prepare(
                new Query(Person.class.getSimpleName())
                    .addFilter("interests",
                        FilterOperator.EQUAL, "books")
                    .addFilter("age",
                        FilterOperator.NOT_EQUAL, null)
                    .addFilter("age",
                        FilterOperator.LESS_THAN, 45))
            .asIterator(), new Function<Entity, Person>() {
          @Override
          public Person apply(final Entity input) {
            return new Person(input);
          }
        });
    while (persons.hasNext()) {
      logger.debug("person: " + persons.next());
    }
    
    final Iterator persons=Iterators.transform(
    数据存储服务
    .准备(
    新查询(Person.class.getSimpleName())
    .addFilter(“兴趣”,
    FilterOperator.EQUAL,“books”)
    .addFilter(“年龄”,
    FilterOperator.NOT_EQUAL,null)
    .addFilter(“年龄”,
    过滤器操作器(小于,45))
    .asIterator(),新函数(){
    @凌驾
    公众人士申请(最终实体输入){
    返回新人员(输入);
    }
    });
    while(persons.hasNext()){
    debug(“person:+persons.next());
    }
    

    这将打印出tom的数据。

    Expando是一个不错的选择,但您必须深入了解如何在java中实现它。谢谢@Gabi,但问题并不是有些属性不是强制性的。问题是什么选项在1方面更好。多条件搜索2。GAE/J/3。属性具有多个值。如果每次谈话都有一篇对应的纯文本文章就好了,因为像我这样的外国人更容易访问它。嗯,有一个PDF包含该页面上的幻灯片,YouTube视频上有字幕。你甚至可以使用谷歌翻译为你翻译幻灯片。谢谢克拉什,这里有很多关于谷歌数据存储如何工作的非常有趣的视频。你提供的链接解决了我提出的3个问题。就我所见,我的备选方案1似乎是最好的选择。
    final Iterator<EAV> eavs = Iterators.transform(
        datastoreService.prepare(
            new Query(EAV.class.getSimpleName()).addFilter("a",
                FilterOperator.EQUAL, "interests").addFilter(
                "v", FilterOperator.EQUAL, "books"))
            .asIterator(), new Function<Entity, EAV>() {
          @Override
          public EAV apply(final Entity input) {
            return new EAV(input);
          }
        });
    while (eavs.hasNext()) {
      logger.debug("eav: " + eavs.next());
    }
    
    final Iterator<EAV> eavs = Iterators.transform(
        datastoreService.prepare(
            new Query(EAV.class.getSimpleName()).addFilter("a",
                FilterOperator.EQUAL, "interests").addFilter(
                "v", FilterOperator.EQUAL, "books").addFilter("a",
                FilterOperator.EQUAL, "age").addFilter(
                "v", FilterOperator.LESS_THAN, 45))
            .asIterator(), new Function<Entity, EAV>() {
          @Override
          public EAV apply(final Entity input) {
            return new EAV(input);
          }
        });
    while (eavs.hasNext()) {
      logger.debug("eav: " + eavs.next());
    }
    
    final Iterator<Person> persons = Iterators.transform(
        datastoreService
            .prepare(
                new Query(Person.class.getSimpleName())
                    .addFilter("interests",
                        FilterOperator.EQUAL, "books")
                    .addFilter("age",
                        FilterOperator.NOT_EQUAL, null)
                    .addFilter("age",
                        FilterOperator.LESS_THAN, 45))
            .asIterator(), new Function<Entity, Person>() {
          @Override
          public Person apply(final Entity input) {
            return new Person(input);
          }
        });
    while (persons.hasNext()) {
      logger.debug("person: " + persons.next());
    }