故事:
假设您正在创建一个网站,人们可以根据自己喜欢的电影互相搜索。因此,您有User
和Movie
作为主要的两个实体。在关联Users
和Movies
以捕捉喜爱电影的概念时,几乎没有选择。
首先:在Movie
User
键列表
模型可能看起来像这样
class User(ndb.Model):
username = ndb.StringProperty()
userid = ndb.IntegerProperty()
email = ndb.StringProperty()
favorite_movies = ndb.KeyProperty(kind=Movie, repeated=True)
class Movie(ndb.Model):
title = ndb.StringProperty()
description = ndb.TextProperty()
第二:为关系创建一个单独的实体
模型可能如下所示
class User(ndb.Model):
username = ndb.StringProperty()
userid = ndb.IntegerProperty()
email = ndb.StringProperty()
class Movie(ndb.Model):
title = ndb.StringProperty()
description = ndb.TextProperty()
class FavoriteMovie(ndb.Model):
user = ndb.KeyProperty(kind=User)
movie = ndb.KeyProperty(kind=Movie)
rating = ndb.IntegerProperty()
采用第二种方法的好处之一是我们可以添加关于关系的其他信息,例如用户给他/她最喜欢的电影的评级。考虑第二种方法的另一个原因是双方是否有很多关系。在这个例子中,用户有很多喜欢的电影,很多用户都喜欢这部电影。
现在说我们不知道人们会不会有很多喜欢的电影,或者电影是否会被很多人所青睐,我们希望能够灵活变通,以便我们不需要匆忙改变设计。此外,您可能希望让用户在某个时刻评价他们喜欢的电影,并再次希望在那里有一些灵活性。但是,我们知道的一件事是,如果这个网站变大,效率就是王道,最终如果灵活性意味着效率降低,我们宁可不要失去效率。第二种方法引起关注,因为文档警告我们需要额外调用数据库来遍历关系。
所以要知道效率是否会成为一个问题,我们需要查看我们需要运行的查询类型,在我们的例子中,最常执行的查询将是“给我所有拥有Forest Gump的用户”作为最喜欢的电影“或”给我所有拥有Forest Gump和Cast Away作为最喜欢的电影的用户“。我们还需要知道我们需要什么数据。我们很可能不需要整个用户回来查询这些查询,而只需要一个名称和一张照片来构建我们在UI上的用户列表。鉴于此,我们可以对我们的数据进行非规范化处理,并将用户的姓名和照片网址放在关系上。执行此操作将允许我们避免对数据库进行后续调用以获取该数据,如果该人实际上选择用户查看他/她的配置文件,那么我们可以调用数据库。
问题:
这些是关于类似于上述问题的想法。正如你可能会说我倾向于使用第二种方法来模拟我的多对多关系。然而,我有一个主要问题。在我给出的第二个查询示例中,我要求Forest Gump AND Cast Away的用户为收藏夹。我不知道如何通过第二种方法有效地完成这项工作,用户能够提出这类问题至关重要。此外,对于使用Forest Gump OR Cast Away作为收藏的用户有什么影响。这些担忧是否足以使用第一种方法,还是有一种更好的方法,我在这里没有考虑过?
我很欣赏有关这个主题的任何想法。
谢谢, 汤姆