отношения parent-> child в appengine python (bigtable) - PullRequest
9 голосов
/ 28 февраля 2011

Я все еще изучаю свои уроки по моделированию данных в bigtable / nosql и буду признателен за некоторые отзывы. Было бы справедливо сказать, что мне следует избегать отношений между родителями и детьми в моем моделировании данных, если мне часто приходится иметь дело с детьми в совокупности по родителям?

В качестве примера давайтеДопустим, я создаю блог, в который будут вносить вклад многие авторы, и у каждого есть посты, а у каждого поста есть теги.Так что я мог бы потенциально настроить что-то вроде этого:

class Author(db.Model): 
  owner = db.UserProperty()

class Post(db.Model): 
  owner = db.ReferenceProperty(Author, 
    collection_name='posts') 
  tags = db.StringListProperty() 

Как я понимаю, это создаст группу сущностей на основе родительского элемента Author. Приводит ли это к неэффективности, если мне в основном нужно запрашивать сообщения по тегам, которые я собираюсь разделить по нескольким авторам?

Я понимаю, что выполнение запроса к свойствам списка может быть неэффективным.Допустим, в каждом посте в среднем около 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') 

И последний вопрос ... что делать, если мой самый распространенный вариант использования будет запрашивать сообщения по нескольким тегам.Например, «найти все посты с тегами в {« яблоки »,« апельсины »,« огурцы »,« велосипеды »}» Является ли один из этих подходов более подходящим для запроса, который ищет посты, имеющие какую-либо коллекциютегов?

Спасибо, я знаю, что это было полным глотком.: -)

Ответы [ 2 ]

5 голосов
/ 28 февраля 2011

Что-то вроде первого или второго подхода хорошо подходит для 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()

Если вы используете строковый тег (нормализованный по регистру) в качестве сущности тега 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)

Третий подход требует дополнительных запросов или выборок для большинства основных операций, и он сложнее, если вы хотите запросить несколько тегов.

2 голосов
/ 28 февраля 2011

Я бы выбрал последний подход, потому что он позволяет получить список сообщений, непосредственно заданных тегом.

Первый подход в основном делает невозможным сохранение канонического набора тегов. Другими словами, вопрос «какие теги в настоящее время присутствуют в системе» очень дорогостоящий.

Второй подход решает эту проблему, но, как я уже упоминал, не помогает вам получать сообщения с тегом.

Группы сущностей немного загадочный зверь, но достаточно сказать, что первый подход НЕ создает группу сущностей, и что они необходимы только * для операций транзакционной базы данных, а иногда полезны для оптимизации данные читаются, но, вероятно, не нужны в небольшом приложении.

Следует отметить, что любой ваш подход будет хорошо работать только в сочетании с разумной стратегией кэширования. Приложения GAE любят кэширование. Познакомьтесь с API memcache и изучите массовые операции чтения / записи в memcache и хранилище данных.

...