моделирование хранилища данных google / python
Привет я пытаюсь построить приложение, которое имеет модели, напоминающие что-то вроде следующих: - (в то время как было бы легко объединить две модели в одну и использовать их , но это не осуществимо в реальном приложении)
class User(db.Model):
username=db.StringProperty()
email=db.StringProperty()
class UserLikes(db.Model):
username=db.StringProperty()
food=db.StringProperty()
Цель-пользователь после входа в систему вводит еду, которая ему нравится, и приложение в свою очередь возвращает всех других пользователей, которым нравится эта еда. Теперь предположим, что пользователь Алиса вводит, что она любит "пиццу", это сохраняется в хранилище данных. Она выходит из системы и входит в систему again.At в этот момент мы запрашиваем хранилище данных для еды, которую она любит, а затем снова запрашиваем для всех пользователей, которым нравится эта еда. Это, как вы видите, два запроса к хранилищу данных, что не самый лучший способ. Я уверен, что был бы определенно лучший способ сделать это. Может кто-нибудь, пожалуйста, поможет.
[Update: - или можно сделать что-то подобное, что я изменю вторую модель таким образом, что имена пользователей станут многозначным свойством, в котором могут храниться все пользователи, которым нравится эта еда.. однако я немного неясно здесь]
[Edit: - Привет, Спасибо за ответ, но я нашел оба решения ниже немного излишним здесь. Я попытался сделать это, как показано ниже.Прошу вас взглянуть на это и дать добрый совет. Я сохранил те же две таблицы, однако изменил их, как показано ниже: -
class User(db.Model):
username=db.StringProperty()
email=db.StringProperty()
class UserLikes(db.Model):
username=db.ListProperty(basestring)
food=db.StringProperty()
Теперь, когда 2 пользователя обновляют одну и ту же еду, которую они любят, она хранится как
'пицца' - - - - > 'Алиса', ' Боб '
И мой запрос к БД для получения данных становится здесь довольно простым
query=db.Query(UserLikes).filter('username =','Alice').get()
Который я могу тогда Повторите как что-то вроде
for elem in query.username:
print elem
Теперь, если есть два продукта, как показано ниже: -
'pizza' ----> 'Alice','Bob'
'bacon'----->'Alice','Fred'
Я использую тот же запрос, что и выше, и перебираю запросы, а затем имена пользователей.
Я совершенно новичок в этом, чтобы понять, что это просто может быть неправильно. Пожалуйста, Предложите!2 ответа:
Помимо модели отношений, которую вы имеете, вы можете справиться с этим двумя другими способами в зависимости от вашего конкретного случая использования. У вас есть хорошая идея в вашем обновлении, используйте свойство ListProperty. Проверьте taslk Бретта Слаткина на индексах отношений для некоторого фона.
Вы можете использовать дочернюю сущность (индекс отношений) для пользователя, содержащего список продуктов:
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)
Однако, что может удовлетворить ваше приложение лучше, было бы сделать отношение ребенком еды:
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)
Если у вас будет много лайков или много пользователей с тем же лайкам, вам нужно будет внести некоторые коррективы в процесс. Вы не сможете получить 1000 пользователей.
Пищевое и пользовательское отношение-это так называемоеМного-ко-многим отношение , типично обрабатываемое с помощью таблицы соединений; в этом случае БД .Модель , которая связывает пользователя и еду. Что-то вроде этого:
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()
Для сущности данного продукта вы можете получить пользователей, которым нравится эта еда с помощью:
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 ключами или, опять же, вы не можете добавить полезные свойства, которые идеально вписывались бы в таблицу join (например, количество звездочек, представляющих, насколько пользователь любит еду).