关系(x> 1)对多

时间:2012-02-26 02:29:10

标签: django postgresql django-models django-queryset

这可能是关于数据库的一般性问题,而不是django,但让我们走了。

我经常被认为是2对多关系。 例如,我的项目中有一个Match类,这是两个团队之间的相遇。

起初,我使用多对多:

Match(Model):
  teams = ManyToManyField('Team', related_name='matches') #Always two teams

最终对匹配相关页面的效率非常低。特别是在django 1.3中,因为没有相当于select_related的many_to_many关系。当你现在只有两个元素时,必须进行迭代会有点痛苦。

然后我切换到这个模型:

Match(Model):
  teams = ManyToManyField('Team', related_name='matches') #Always two teams
  team1 = ForeignKey('Team')
  team2 = ForeignKey('Team')

当我想显示与匹配相关的页面时,我可以使用select_related并非常有效地显示两个团队。 当我在团队页面上时,我可以按照“匹配”关系来获得所有匹配。 但我发现处理一种关系的3个领域是完全可怕的。

我做得对吗?你会推荐什么?

1 个答案:

答案 0 :(得分:1)

我在那里看到的解决方案很少。

<强> 1

如果您预计未来的比赛将在其他球队之间进行,那么您可能最好从第二个设计中删除ManyToMany字段:

Match(Model):
  team1 = ForeignKey('Team')
  team2 = ForeignKey('Team')

它将删除数据库中的冗余并使Match修改更容易(您不必担心team字段与相应team1之间的内聚,{{1} } fields)。它也不可能与其他数量的相应团队创建匹配而不是两个,这将导致数据库的一致性。

另一方面,你失去了灵活性并且编写查询更加困难,因为要检查两个字段而不是一个字段。

<强> 2

您可能想要使用缓存。实际上 - 您拥有的这两个字段只不过是这样,但将其移动到专用缓存数据库可以提高效率并将主数据库与缓存值分离,从而使数据库设计更加清晰。

第3

编写自己的ManyToMany抓取器。这不是很难,但相当丑陋。您必须选择您感兴趣的团队,然后以某种方式将它们附加到Match对象,例如:

team2

<强> 3.5

新版本的Django将使用matches # Match QuerySet related_teams = Team.objects.filter(match__in=matches) matches_map = {} for t in related_teams: matches_map[t.match_id]= matches_map.get(t.match_id, []).append(t) for m in matches: m.fetched_teams = matches_map[m.pk] 方法,该方法适用于ManyToMany查询,但我认为您没有那么多时间。