如何从关系数据库思维模式转变为应用引擎数据存储?

How to move from a relational database mindset to app-engine datastore?

这个问题看起来像一个开放式的问题。为了更具体,让我用一个示例场景来解释。

假设玩家 P1、P2、...、Pn 为球队 T1、T2、...、Tm 效力。每年都有球队竞标球员,因此球员不断更换球队。

在关系数据库中,球员和球队模式之间存在 N 对 N 关系。我们可以轻松地从关系数据库中获取以下信息:-

  1. 球员P1整个职业生涯进了多少球?
  2. 球员P1整个职业生涯为T1队打进了多少球?

在关系型数据库中,目标可能是N-N关系PlayerTeam的一个属性。回答 (1) 只是一个聚合 SUM 查询,而 (2) 是一个简单的 select 查询。

我们如何在 Google App Engine 数据存储中组织团队和玩家?以及如何在 Datastore 中运行上面的查询 (1) 和 (2)?

这是一个简单但可行的方法:

import ndb

class Player(ndb.model):
    name = ndb.StringProperty(required=True)
    # rest of Player model snipped

class Team(ndb.model):
    name = ndb.StringProperty(required=True)
    # rest of Player model snipped

class Goal(ndb.model):
    player = ndb.KeyProperty(Player, required=True)
    team = ndb.KeyProperty(Team, required=True)

def playerNumGoals(player):
    qry = Goal.query().filter(Goal.player == player.key())
    return qry.count()

def playerTeamNumGoals(player, team):
    qry = Goal.query().filter(Goal.player == player.key(),
                              Goal.team == team.key())
    return qry.count()

因此,在这种情况下与关系方法没有太大区别,除了您使用显式查询而不是联接。有了适当的索引,它就差不多了。

其他用例要困难得多,可能需要更深入的重组(通常是某种程度的反规范化)来解决缺少连接的问题——在 ndb 中就像在任何其他 NoSQL 数据库方法中一样. ndb 有它自己的额外怪癖(例如,某些 属性 不能 select 与 23 不同,但可以按不同的 属性 排序),如果您有时需要大量的独创性正在处理令人印象深刻的大量数据...