Как сгладить модель "дружбы" внутри модели User в GAE?

Недавно я наткнулся на ряд статей, указывающих на выравнивание данных для баз данных NoSQL. Исходя из традиционных баз данных SQL, я понял, что реплицирую поведение базы данных SQL в GAE. Поэтому я начал проводить рефакторинг кода, где это возможно.

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

class Friendship(ndb.Model):
   from_friend = ndb.KeyProperty(kind=User)
   to_friend = ndb.KeyProperty(kind=User)

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

friendshipA = Friendship(from_friend = UserA, to_friend = userB)
friendshipB = Friendship(from_friend = UserB, to_friend = userA)

Как я мог теперь перенести это в реальную модель пользователя, чтобы сгладить это. Я подумал, может быть, я мог бы использовать StructuredProperty. Я знаю, что это ограничено 5000 записей, но этого должно быть достаточно для друзей.

class User(UserMixin, ndb.Model):
     name = ndb.StringProperty()
     friends = ndb.StructuredProperty(User, repeated=True)

Так что я придумал это, однако Пользователь не может указать на себя, так что кажется. Потому что я получаю NameError: name 'User' is not defined

Любая идея, как я могу сгладить это так, чтобы один экземпляр пользователя содержал всех своих друзей со всеми их свойствами?

2 ответа

Решение

Вы не можете создать StructuredProperty, который ссылается на себя. Кроме того, использование StructuredProperty для хранения копии User имеет дополнительную проблему необходимости выполнения ручного каскадного обновления, если пользователь когда-либо изменяет сохраняемое свойство.

Тем не менее, в качестве KeyProperty принять String как kindВы можете легко сохранить список пользователей, используя KeyProperty, как предложено @dragonx. Вы можете дополнительно оптимизировать чтение с помощью ndb.get_multi чтобы избежать нескольких вызовов RPC туда-обратно при поиске друзей.

Вот пример кода:

class User(ndb.Model):
     name = ndb.StringProperty()
     friends = ndb.KeyProperty(kind="User", repeated=True)

userB = User(name="User B")
userB_key = userB.put()

userC = User(name="User C")
userC_key = userC.put()

userA = User(name="User A", friends=[userB_key, userC_key])
userA_key = userA.put()

# To retrieve all friends
for user in ndb.get_multi(userA.friends):
    print "user: %s" % user.name

Используйте KeyProperty, в котором хранится ключ для экземпляра User.

Другие вопросы по тегам