如何在KeyProperty链接实体的属性上有效地制作app-engine-ndb子查询?

时间:2015-11-12 21:35:42

标签: python google-app-engine google-cloud-datastore app-engine-ndb

随着时间的推移,可以将组装的团队部署到多个项目

在此示例中,我想查询分配给'活跃'仅限项目。我正在使用的代码正在运行,但我想知道是否有更高效/紧凑的方法。

模型

class Team(ndb.Model):
    """Model for representing an project team."""
    teamid = ndb.StringProperty(required=True)
    project = ndb.KeyProperty(kind='Project', required=True, repeating=True)

class Project(ndb.Model):
    """Model for representing a Project"""
    name = ndb.StringProperty(required=True)
    status = ndb.StringProperty(required=True)

查询

status = 'active'

project_query = Project.query()\
    .filter(Project.status == status)

active_projects = project_query.fetch(1000, keys_only=True)

team_query = Team.query().order(Team.teamid)\
    .filter(Team.projectid.IN(active_projects))

results = team_query.fetch(max_results, offset=start_at)

紧凑形式基本上相同的东西

team_query = Team.query().order(Team.teamid)\
    .filter(Team.projectid.IN(Project.query().filter(Project.status == status)
        .fetch(1000, keys_only=True)))

有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

您可以通过“冗余”在Team实体上具有project_status属性来对数据模型进行反规范化,并保持与相应Project实体上的status属性相同。 / p>

当然,缺点是“更改项目状态”还需要找到分配给该项目的所有团队并相应地更改其project_status(并且您可能需要多个实体组事务)。但最重要的是,将所有分配给项目的团队定位在特定状态会变得更快,只需一个简单的查询。

这种权衡对于与数据模型去标准化相关的决策非常典型。如果在您的应用程序中,项目状态变化相对较少(并且通常可能只有少数团队被分配给给定项目),而对“在特定状态下分配给项目的所有团队”的查询频繁且需要快速,那么de - 标准化将是一个值得优化的。

更加抽象化,哪些去规范化是值得的,它总是高度依赖于特定的应用程序约束 - 查询或更新很少或频繁,每个操作的性能目标是什么。你也总是付出更多数据的代价,因为有些东西是重复的。另一方面,许多应用程序具有相对罕见的写入/更新,以及非常频繁的读取/查询,这往往倾向于明智的去规范化。

答案 1 :(得分:1)

由于团队和项目之间存在多对多的关系,因此您可以选择是否与团队合作:

project = ndb.KeyProperty(kind='Project', required=True, repeating=True)

或项目:

team = ndb.KeyProperty(kind='Team', required=True, repeating=True)

您可以通过仅使用一个查询和ndb.get_multi()来改进查询中的查询。查询很慢,获取速度更快(尤其是在memcached时)。通过更改模型,您可以改善查询。

class Team(ndb.Model):
    """Model for representing an project team."""
    teamid = ndb.StringProperty(required=True)

class Project(ndb.Model):
    """Model for representing a Project"""
    name = ndb.StringProperty(required=True)
    status = ndb.StringProperty(required=True)
    team = ndb.KeyProperty(kind='Team', required=True, repeating=True)

现在您可以按状态查询并执行get:

status = 'active'

project_query = Project.query()\
    .filter(Project.status == status)

active_projects = project_query.fetch(1000, keys_only=True)

teams = set()
for project in active_projects:
    teams.extend(project.team)

results = ndb.get_multi(list(teams))

(感谢Tim Hoffman对这种方法的评论。)