关系

关系表示 Cloud SQL 模型中各记录之间的潜在关联。它体现了一条记录与其他一条或多条记录建立关联的能力。例如,社交应用中的 Person 模型可以包含 Friends 关系,用以体现两个人之间的友好关系。

关系基础知识

在应用制作工具中,关系是双向的。每个方向称为一个关联方,而每个关联方具有两个属性:

  • Name - 关联方的名称,用于指代数据绑定和脚本中的关系。
  • Count - 关联方支持的连接数。Count 可以设置为 one(表示记录只接受一个连接)或 many(表示记录接受无限多个连接)。支持的关系是 one-to-one(一对一)、one-to-many(一对多)和 many-to-many(多对多)。此 count-to-count 值称为基数或关联度

例如,在 HR 应用中,您可以使用 EmployeeDBTeams 模型之间的关系来表示员工及其所属团队。您可以在 EmployeeDBTeams 之间创建多对多关系,因为每位员工可以属于多个团队。两个关联方具有如下属性:

  • Name=Members,Count=Many
  • Name=Teams,Count=Many

您还可以在 EmployeeDBTeams 之间创建一对多的关系,因为每个小组可以有一个经理,而一个经理可以有多个小组。两个关联方具有如下属性:

  • Name=Manager,Count=One
  • Name=Teams,Count=Many

创建和修改关系

如需创建关系,请执行以下操作:

  1. 点击 Cloud SQL 模型,然后转到其 Relations 标签页。
  2. 要创建关系,请点击 Add Relation。您可以使用创建向导执行以下操作:

    1. 设置另一个关联方的目标模型。
    2. 选择每个关联方对应的 Count。
    3. (可选)输入每个关联方的名称(如果您不想保留默认值)。
    4. (可选)对于一对一关系和一对多关系,请为 Count 为 one 的关联方选择所有者。只有在满足以下条件的情况下,才能在关系中指定所有者模型:
  3. 点击 Create

创建关系后,您可以修改关联方的名称。对于 Count 为 one 的关联方,您可以启用或停用所有权。对于 Count 为 many 的关联方,您可以更改其排序方式。

如需修改关系,请执行以下操作:

  1. 点击模型,然后转到其 Relations 标签页。
  2. 在关系列表中,点击关联方名称。

    对于连接两个模型中记录的关系,每个模型的关系列表仅显示另一个模型的关联方名称。对于连接同一模型中记录的关系,两个关联方均会列出。在 EmployeeDB 模型示例中,ManagerMembers 均列在 Relations 标签页上。

  3. 修改名称、所有者或排序。您所做的更改会自动保存。

    要设置排序,请选择要用于对记录进行排序的字段。选中升序复选框可设置关联方记录的排序顺序。如果您未指定排序偏好设置,则模型的数据后端会自动确定排序顺序。

关联记录的所有权

对于至少有一个关联方的 Count 属性为 one 的关系,您可以指定所有者,但受限于某些规则。设置所有者时,您可以为两个模型中的关联记录创建所有者-自有关系:

  • 具有所有权 - 如果用户或应用逻辑从所有者模型中删除记录,则该应用将删除所有关联的自有记录。如果删除自有记录,则所有者记录不会随之删除。
  • 不具所有权 - 任一关联方的记录被删除时,另一方的记录不会随之删除。

只有在同时符合以下条件的情况下,才能在关系中指定所有者模型:

  • 如果没有相应的所有者记录,就不应存在自有记录
  • 如果所有者记录被删除,您希望关系中的自有记录随之一起自动删除。

所有权示例

您可能希望帐单项随帐单一起删除。InvoiceItem 之间的一对多关系使 Invoice 模型成为所有者。如果用户删除 Invoice 记录,则该应用还会删除所有自有的 Item 记录(即与所删除 Invoice 记录关联的记录)。

请注意,删除的记录表示项的特定实例(例如,库存中的特定光盘驱动器),而不是项类别(例如,您库存的光盘驱动器类型)。

所有权规则

  • 对于一对一关系或一对多关系,只能将其中一方的模型设为所有者。
  • 如果将某个模型指定为所有者会形成所有权循环(例如记录 A 拥有记录 B,而记录 B 又拥有记录 A),则不能执行此操作。
  • 您可以将所有者自有的关系串接起来。例如,如果您拥有以下模型和关系:

    • ForumTopicComment 模型
    • ForumTopic 之间具有一对多关系,其中 型为所有者
    • TopicComment 之间具有一对多关系,其中 型为所有者

    删除 Topic 记录后,应用制作工具也会删除所有关联的 Comment 记录。删除 Forum 记录后,应用制作工具也会删除所有关联的 Topic 记录及其关联的 Comment 记录。

  • 具有多个关系的模型可以归多个所有者模型拥有。

  • 如果您从所有者模型中删除某条记录,则应用制作工具会从其他模型中删除该记录拥有的记录,即使这些记录还同时归其他模型中的记录所有也是如此。

管理记录之间的关联

关联是指两条记录通过模型关系建立的实际关系。例如,如果 ManagerTeams 之间存在一对多关系,则 Manager1 的记录与每个小组的记录之间是有关联性的。

您可以通过三种方式创建和修改记录之间的关联,具体取决于应用的工作流:

  1. 使用数据绑定可以让微件显示或更改记录的关联。
  2. 使用客户端脚本可以处理比数据绑定更加复杂的关联更改。
  3. 使用服务器脚本可以处理批量更改或进行安全更改。

使用数据绑定修改关联

您可以通过多种方式使用数据绑定更改记录之间的关联,但最简单的方式是将关联方作为模型数据源的 item 的属性进行访问。在模型数据源中,关联方作为记录属性公开,与字段非常相似。

如需使某个微件能够显示或更改当前所选记录的关联记录,请将该微件的 value 绑定到 @datasource.item.[relation end name]。这种方法非常适用于下拉列表微件(当关联方的 Count 为 one 时)和多选框微件(当关联方的 Count 为 many 时)。例如,请试用连接数据模型教程;当您创建用于列出员工的界面元素时,您可以设置微件值和数据源之间的绑定。

使用客户端脚本修改关联

这种方法比数据绑定更复杂一些,因为您需要确保数据源已经加载记录的相关记录。您可以通过以下方式确保关联的记录已加载完毕:

  • 为数据源启用预提取功能
  • 在记录上调用 _loadRelation-name,并等待异步回调
  • 等待关系数据源的 onLoad 事件
  • 等待使用关系数据源的微件的 onDataLoad 事件

例如,如需基于上文中 EmployeeDB - Team 之间的关系场景构建应用,您可以使用以下代码关联记录(将经理的角色分配给一个团队成员并将该团队成员添加到经理团队)。为了更轻松地访问正确的员工记录,您在 EmployeeDB 模型中创建了两个数据源:

  1. Manager,用于选择经理
  2. Member,用于选择团队成员
    var managerRecord = app.datasources.Manager.item;
        var teamRecord = app.datasources.Teams.item;

        // Assign the manager to the team.
        teamRecord.Manager = managerRecord;

        // Changes are saved automatically if the datasource in auto-save mode

        // Add a team member to a Manager's team.
        // Note: Retrieve Members on the client before proceeding, such as by using prefetch option in datasource - datasources Team -> Members)
        var engineerRecord = app.datasources.TeamMember.item;
        teamRecord.Members.push(engineerRecord);
    

使用服务器脚本修改关联

使用服务器脚本修改关联比使用客户端脚本更容易,因为您不必在何时加载关联记录上费心。您只需访问相应记录,然后使用其关联方属性通过关系关联记录即可。

例如,如需基于上文中 EmployeeDB - Team 之间的关系场景构建应用,您可以使用以下服务器脚本将经理和成员添加到团队中:

// Get the record for the Team to modify.
    var teamRecord = app.models.Teams.getRecord("team1");

    // Assign a manager to the Team.
    var managerRecord = app.models.EmployeeDB.getRecord("manager1");
    teamRecord.Manager = managerRecord;

    // Note: The new association is not saved yet

    // Assign a team member to the Team.
    var engineerRecord = app.models.EmployeeDB.getRecord("engineer1");
    teamRecord.Members.push(engineerRecord);

    // Save both changes to the database.
    app.saveRecords([teamRecord]);
    

关系过滤

如需按相关 Cloud SQL 模型中的字段过滤或排序记录,请添加一个或多个关系名称,并在其后附上字段名称。例如,如需按相关记录的 Age 字段过滤 Mother 关系,请使用 Mother.Age

您还可以在关联的记录或记录键上应用 equalsnotEqualsinnotIn 过滤条件。例如,如需检查分派的上上级经理是否正确,您可以按 Manager.Manager._key._equals 进行过滤。

关系过滤适用于数据绑定服务器脚本

更多详情