Relations express potential connections between records. Think of a relation as the ability for one record to be associated with another. For example, a
Person model in social app could have a
Friends relation that represents friendship between two people.
Relations in App Maker are bidirectional. Each direction is called a relation end, and each relation end has two properties:
- Name: The relation end's name, used to refer to the relation in data binding and scripts.
- Count: The number of connections the relation end supports. Count can be set to one, meaning the record only accepts one connection, or many, allowing unlimited connections. The relationships that result can be one-to-one, one-to-many, and many-to-many. These are known as cardinality and as the degree of the relationship.
For example, an HR app could use relations to represent a manager and their team:
- Name: Manager, Count: One
- Name: TeamMember, Count: Many
With this relation, a manager could have multiple team members, but each team member can only have one manager.
Create and edit relations
Create and edit relations in a model's Relations tab. Click Add New Relation to create a new relation. The creation wizard lets you select both relation ends' names and count and set a target model for one of the ends.
Edit relations by selecting an relation end name from the list below the Add New Relation button. For relations that connect two models, the relation list only displays the relation end name of the opposite model. Using the example above, if
TeamMember were two different models, the
Manager relation tab would display a
TeamMember relation and vice versa.
Relation end sorting
The Sort By drop-down in the relation editor specifies the field that App Maker should use to sort records of a relation end. The Ascending checkbox specifies the sorting order of records for the relation end. Sorting only applies to relation ends that have a count of many. If you don't specify a sorting preference, the model's data backend determines the sorting order.
Ownership of associated records
You can specify Owner for a model on one end of a relation (subject to some rules). Doing so creates an owner-owned relationship for associated records in the two models:
- With ownership—When a user or app logic deletes a record from the owner model, the app deletes all associated owned records. Deleting owned records doesn't delete owner records.
- Without ownership—Deleting records on either end of the relation doesn't delete records on the other end.
Only specify an owner model in a relation if owned records shouldn't exist without their owner records, and if you want automatic deletion of records on the owned end of the relation.
Specifying a model as an owner doesn't affect the mechanisms for associating or deleting records.
It might make sense to delete invoice items when an invoice is deleted. With a one-to-many relation between the Invoice and Item models, make the Invoice model the owner. When a user deletes an Invoice record, the app also deletes all owned Item records (records that were associated with the deleted Invoice record).
Note that these are specific instances of items (for example, specific disc drives from inventory), not categories of items (for example, kinds of disc drives that you stock).
- Only the model on the one side of a one-to-one or one-to-many relation can be an owner.
- You can't designate a model as an owner if that would create a cycle in ownership (something like record A owning record B and record B owning record A).
You can chain owner-owned relations. For example:
- Forum, Topic, and Comment models
- A one-to-many relation from Forum to Topic, with the Forum model as the owner
- A one-to-many relation from Topic to Comment, with the Topic model as the owner
Deleting a Topic record also deletes all associated Comment records. Deleting a Forum record deletes all associated Topic records and their associated Comment records.
Owner models in different relations can own the same owned model.
Deleting a record from an owner model deletes that record's owned records from other models, even if the owned records are also owned by records in other models.
Modify associations with a data binding
There are many ways to change the associations between records through data bindings, but the simplest is to access a relation end as a property of a model datasource's
item. In model datasources, relation ends are exposed as record properties, much like fields.
Bind a widget's
@datasource.item.[relation end name], to let the widget display or change associated records for the currently-selected record. This method is especially useful for dropdown widgets and multiselect boxes, for relation ends with a count of one or many, respectively.
Modify associations with a client script
Modifying associations in client scripts is more difficult than doing it through data bindings. In client scripts, you need to ensure that the appropriate datasource has already loaded the record's associated records. You can do this by specifying prefetch on the datasource, by waiting for the
onLoad event of a relation datasource, or by waiting for the
onDataLoad event of a widget that uses a relation datasource.
Assuming that associated records are loaded, the following code could be used to associate records with the
TeamMember relation ends in the example above:
var managerRecord = app.datasources.Manager.item; var teamMemberRecord = app.datasources.TeamMember.item; // Assign a TeamMember to a Manager. teamMemberRecord.Manager = managerRecord; // Add a TeamMember to a Manager's team: // first get the manager's current team, // this will be "null" if the relation isn't loaded. var team = managerRecord.TeamMember; // Next, add the TeamMember to it. team.push(teamMemberRecord);
Modifying associations with a server script
Modifying associations in server scripts is easier than in client scripts, because you don't have to worry about loading associated records. Access the appropriate record, then use its relation end properties to associate records through the relation:
var managerRecord = app.models.Manager.getRecords(["manager1"]); var teamMemberRecord = app.models.TeamMember.getRecords(["teamMember1"]); // Assign a Manager to a TeamMember. teamMemberRecord.Manager = managerRecord; // Add an TeamMember to an Manager's team. managerRecord.TeamMember.push(teamMemberRecord); app.saveRecords([teamMemberRecord, managerRecord]);
To filter or sort records by a field in a related Cloud SQL model, add the relation name or names followed by a field name. For example, to filter a
Mother relation by the related records'
Age field, use
You can also apply
notIn filters on an associated record or record key. For example, to check that a manager's manager is assigned correctly, you could filter by