моделирование хранилища данных Google / Python - PullRequest
3 голосов
/ 22 октября 2010

Привет, я пытаюсь создать приложение, в котором есть модели, похожие на приведенные ниже :-( Хотя было бы легко объединить две модели в одну и использовать их, но в реальном приложении это невозможно)

class User(db.Model):
     username=db.StringProperty()
     email=db.StringProperty()

class UserLikes(db.Model):
      username=db.StringProperty()
      food=db.StringProperty()

Цель - пользователь после входа в систему вводит понравившуюся ему еду, а приложение в свою очередь возвращает всех остальных пользователей, которым эта еда нравится.Теперь предположим, что пользователь Алиса вводит, что ей нравятся «Пиццы», они сохраняются в хранилище данных.Она выходит из системы и снова входит в систему. В этот момент мы запрашиваем в хранилище данных понравившуюся ей еду, а затем снова запрашиваем всех пользователей, которым она нравится.Как вы видите, это два запроса к хранилищу данных, что не является лучшим способом.Я уверен, что был бы лучший способ сделать это.Может кто-нибудь, пожалуйста, помогите.

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

[Edit: -Hi Спасибо за ответ, но я нашел оба решения ниже немного излишним здесь.Я попытался сделать это, как показано ниже. Просим вас взглянуть на это и любезно дать совет.Я сохранил те же две таблицы, но изменил их, как показано ниже: -

class User(db.Model):
    username=db.StringProperty()
    email=db.StringProperty()

class UserLikes(db.Model):
     username=db.ListProperty(basestring)
     food=db.StringProperty()

Теперь, когда 2 пользователя обновляют одну и ту же еду, которая им нравится, она сохраняется как

'pizza' ----> 'Алиса', 'Боб'

И мой запрос к БД для получения данных здесь становится довольно простым

query=db.Query(UserLikes).filter('username =','Alice').get()

, который я затем могу повторять как что-то вроде

    for elem in query.username:
          print elem

Теперь, если есть два продукта, как показано ниже: -

'pizza' ----> 'Alice','Bob'
'bacon'----->'Alice','Fred'

Я использую тот же запрос, что и выше, и перебираю запросы, а затем имена пользователей.

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

Ответы [ 2 ]

2 голосов
/ 22 октября 2010

Помимо имеющейся у вас модели отношений, вы можете обрабатывать это двумя другими способами, в зависимости от вашего конкретного случая использования. У вас есть хорошая идея в вашем обновлении, используйте ListProperty. Проверьте задание Бретта Слаткина по Индексы отношений для некоторого фона.

Вы можете использовать дочернюю сущность (индекс отношений) для пользователя, который содержит список продуктов:

class UserLikes(db.Model):
    food = db.StringListProperty()

Затем, когда вы создаете экземпляр UserLikes, вы определяете пользователя, к которому он относится, в качестве родителя:

likes = UserLikes(parent=user)

Это позволяет вам запрашивать других пользователей, которым нравится определенная еда:

like_apples_keys = UserLikes.all(keys_only=True).filter(food='apples')
user_keys = [key.parent() for key in like_apples_keys]
users_who_like_apples = db.get(user_keys)

Тем не менее, то, что может подойти вашему заявлению лучше, это сделать Relation ребенком пищи:

class WhoLikes(db.Model):
    users = db.StringListProperty()

Установите key_name для названия еды при создании подобного:

food_i_like = WhoLikes(key_name='apples')

Теперь, чтобы получить всех пользователей, которым нравятся яблоки:

apple_lover_key_names = WhoLikes.get_by_key_name('apples')
apple_lovers = UserModel.get_by_key_names(apple_lover_key_names.users)

Чтобы получить всех пользователей, которым нравится то же самое, что и пользователю:

same_likes = WhoLikes.all().filter('users', current_user_key_name)
like_the_same_keys = set()
for keys in same_likes:
   like_the_same_keys.union(keys.users)
same_like_users = UserModel.get_by_key_names(like_the_same_keys)

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

1 голос
/ 22 октября 2010

Пища и пользовательское отношение - это так называемое отношение «многие ко многим» , которое обычно обрабатывается таблицей соединений; в этом случае db.Model , который связывает пользователя и еду. Как то так:

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

  def get_food_I_like(self):
     return (entity.name for entity in self.foods)

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

  def get_users_who_like_me(self):
    return (entity.name for entity in self.users)

class UserFood(db.Model):
  user= db.ReferenceProperty(User, collection_name='foods')
  food = db.ReferenceProperty(Food, collection_name='users')

Для объекта данного пользователя вы можете получить предпочтительную еду с помощью:

userXXX.get_food_I_like()

Для данного объекта Food вы можете получить пользователей, которым нравится эта еда, с помощью:

foodYYY.get_users_who_like_me()

Существует также другой подход для обработки отношений «многие ко многим», хранящих список ключей внутри db.ListProperty().

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

class User(db.Model):
  name = db.StringProperty()
  food = db.ListProperty(db.Key)

Помните, что ListProperty ограничен 5.000 ключами или снова, вы не можете добавить полезные свойства, которые идеально вписались бы в таблицу соединений (например: количество звездочек, представляющих, как пользователь любит еду).

...