我还在学习bigtable / nosql中关于数据建模的课程,并希望得到一些反馈。 如果我经常需要在父母之间共同处理这些孩子,我是否应该避免在我的数据建模中避免使用父与子关系?
作为一个例子,假设我正在建立一个由许多作者贡献的博客,彼此有帖子,每个帖子都有标签。所以我可能会设置这样的东西:
class Author(db.Model):
owner = db.UserProperty()
class Post(db.Model):
owner = db.ReferenceProperty(Author,
collection_name='posts')
tags = db.StringListProperty()
据我所知,这将创建一个基于作者父级的实体组。 如果我主要需要通过标签查询帖子,这是否会导致效率低下,我期望在多个作者之间进行查询?
我理解对列表属性进行查询可能效率低下。假设每个帖子平均有大约3个标签,但可以一直到7个。我希望我的可能标签集合可以达到数百个。 将此模型更改为此类似乎有什么好处吗?
class Author(db.Model):
owner = db.UserProperty()
class Post(db.Model):
owner = db.ReferenceProperty(Author,
collection_name='posts')
tags = db.ListProperty(db.Key)
class Tag(db.Model):
name = db.StringProperty()
或者我会做这样的事情会更好吗?
class Author(db.Model):
owner = db.UserProperty()
class Post(db.Model):
owner = db.ReferenceProperty(Author,
collection_name='posts')
class Tag(db.Model):
name = db.StringProperty()
class PostTag(db.Model):
post = db.ReferenceProperty(Post,
collection_name='posts')
tag = db.ReferenceProperty(Tag,
collection_name='tags')
最后一个问题......如果我最常见的用例是通过多个标签查询帖子怎么办?例如,“在{'apples','oranges','cucumbers','bicycles'}中找到包含标签的所有帖子”这些方法中的一种更适合查找具有任何集合的帖子的查询标签?
谢谢,我知道那是满口的。 : - )
答案 0 :(得分:5)
第一种或第二种方法非常适合App Engine。请考虑以下设置:
class Author(db.Model):
owner = db.UserProperty()
class Post(db.Model):
author = db.ReferenceProperty(Author,
collection_name='posts')
tags = db.StringListProperty()
class Tag(db.Model):
post_count = db.IntegerProperty()
如果您使用字符串标记(case-normalized)作为Tag实体key_name,您可以有效地查询具有特定标记的帖子,或列出帖子的标记或获取标记统计信息:
post = Post(author=some_author, tags=['app-engine', 'google', 'python'])
post_key = post.put()
# call some method to increment post counts...
increment_tag_post_counts(post_key)
# get posts with a given tag:
matching_posts = Post.all().filter('tags =', 'google').fetch(100)
# or, two tags:
matching_posts = Post.all().filter('tags =', 'google').filter('tags =', 'python').fetch(100)
# get tag list from a post:
tag_stats = Tag.get_by_key_name(post.tags)
第三种方法需要对大多数基本操作进行额外的查询或提取,如果要查询多个标记则更加困难。
答案 1 :(得分:2)
我会选择最后一种方法,因为它允许直接检索给定标签的帖子列表。
第一种方法基本上不可能保留规范的标签集。换句话说,“系统中当前存在什么标签”的问题是非常昂贵的。
第二种方法解决了这个问题,但正如我所提到的,它无法帮助您检索给定标记的帖子。
实体组有点神秘,但只要说第一种方法不创建实体组,并且它们只是必要用于事务数据库操作,有时候对于优化的数据读取,但在一个小的应用程序中可能是不需要的。
应该提到的是,您采取的任何方法都只能与智能缓存策略配合使用。 GAE应用程序喜欢缓存。与memcache api保持密切联系,了解memcache和数据存储区的批量读/写操作。