Как сгладить модель "дружбы" внутри модели 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.