Google app engine GAE/J中的数据库设计:关系建模与实体属性值
假设您计划创建一个运行在GAE/Java上的社交网络,其中每个用户都有一组属性(即年龄、当前城镇、兴趣) 备选方案1:经典方法-将用户id和每个属性作为“行” 备选方案2:实体atributte值(EAV) 您认为每个选项有哪些优点/缺点?我主要关注的是: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含义?(即索引、数据存储大小…) 如果要检索“喜欢书籍的用户”,如何使用多个值(例如“兴趣”)对属性建模 我认为第二种选择更灵活,可能更容易实
谢谢。你看过谷歌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());
}