parent-> appengine python中的子关系(bigtable)

时间:2011-02-28 06:51:44

标签: python google-app-engine database-design nosql bigtable

我还在学习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'}中找到包含标签的所有帖子”这些方法中的一种更适合查找具有任何集合的帖子的查询标签?

谢谢,我知道那是满口的。 : - )

2 个答案:

答案 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和数据存储区的批量读/写操作。