Python: моделирование отношений один-к-одному в хранилище данных - PullRequest
4 голосов
/ 09 августа 2011

Предположим, у нас есть две модели: User и Token.У пользователя может быть только один Token, а Token может принадлежать только одному пользователю.

Исходя из реляционных баз данных, следующий способ выглядит как :

class User(db.Model):
    name = db.StringProperty()

class Token(db.Model):
    name = db.StringProperty()
    owner = db.ReferenceProperty(User)

Это, конечно, также создаст User.token_set, то есть db.Query.Но я бы очень хотел получить доступ к токену, скажем, User.token вместо User.token_set.get(), так как насчет ..

class User(db.Model):
    name = db.StringProperty()
    token = db.ReferenceProperty(Token)

class Token(db.Model):
    name = db.StringProperty()
    owner = db.ReferenceProperty(User)

Теперь я могу получить к ним двунаправленный доступ: User.token & User.owner.И просто игнорируйте тот факт, что у меня есть эти автоматически созданные .token_set и user_set.

Что-то не так с этим?С логической стороны, с точки зрения производительности?

Может быть, у меня не должно быть даже двух моделей.Оба они на практике содержат четыре-пять свойств.Должны ли они просто быть одним?Когда отношения «один к одному» должны быть разорваны, просто объединены в одну модель?

Спасибо за любой вклад!

Ответы [ 2 ]

4 голосов
/ 09 августа 2011

это хранилище данных appengine.это не sql.Вы должны сгруппировать данные так, как они используются вашей системой.по-видимому, у вас есть места, где пользователи и токены используются вместе, и, поскольку нет проблем со многими к одному, они могут идти в одном экземпляре модели.это даст вам лучшую производительность (например, намного более простой поиск пользователя по токену) и более простую обработку согласованности (обновление токена и пользователя будет происходить в рамках одной транзакции).

я не знаю, является лисвязывание здесь допустимо, так что, возможно, кто-то отредактирует это, если нет, но я написал http://acooke.org/cute/LessonsLea2.html, чтобы попытаться собрать воедино мой опыт работы с хранилищем данных.Вы можете найти это полезным.

[править: один способ подумать об этом: вы не моделируете данные.Вы пишете систему, которая предназначена для масштабирования.это - а не моделирование данных - это то, что движет всем.Я не говорю, что это хорошая идея, но это то, что делает appengine.если вашим главным приоритетом является моделирование данных - например, если вы хотите, чтобы несколько приложений использовали ваши данные по-разному - тогда вам не следует использовать appengine.]

1 голос
/ 12 августа 2011

Добавление токена в ссылку на класс пользователя имеет свои плюсы и минусы. В качестве преимущества вы получите лучшую производительность при поиске токенов. Как минусы, вам потребуется больше транзакций при вставке данных.

user = User(name='john').put()
token = Token(name='somehash', user=user).put()
user.token = token
user.put()

Вам также приходится иметь дело с нулевыми ссылками при удалении токенов.

Возможно, вы можете использовать декораторы классов, если вам нужен синтаксис сахар:

class User(db.Model):
    name = db.StringProperty()

    @property
    def token(self):
        if not hasattr(self, '_token_cached'):
            setattr(self, '_token_cached', self.token_set.get())
       return self._token_cached
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...