リレーション

リレーションは Cloud SQL モデル内のレコードの関連性を表します。1 つのレコードを複数のレコードに関連付けることもできます。たとえば、ソーシャル アプリの Person モデルで Friends リレーションを使用し、2 人の人物の友人関係を定義できます。

リレーションの基本

App Maker のリレーションは双方向です。リレーションの両端はリレーション エンドといいます。リレーション エンドには次の 2 つのプロパティを設定します。

  • Name - リレーション エンドの名前。データ バインディングとスクリプトでリレーションを参照する場合に使用します。
  • Count - リレーション エンドでサポートされる接続数。このカウントを One に設定すると、レコードは 1 つの接続のみを受け入れます。Many に設定すると、レコードが受け入れる接続数に上限はなくなります。リレーションは、1 対 1、1 対多、多対多のいずれかになります。これは、リレーションのカーディナリティまたは多重度を表します。

たとえば、HR アプリでは、EmployeeDB モデルと Teams モデル間のリレーションを使用して、従業員と所属チームを表します。1 人の従業員が複数のチームに所属する可能性があるため、EmployeeDBTeams の間に多対多のリレーションを作成します。リレーション エンドには次のプロパティを設定します。

  • Name=Members、Count=Many
  • Name=Teams、Count=Many

各チームのマネージャーは 1 人だけですが、1 人のマネージャーが複数のチームを担当する場合があるため、EmployeeDBTeams の間に 1 対他のリレーションを作成します。リレーション エンドには次のプロパティを設定します。

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

リレーションの作成と編集

リレーションを作成するには:

  1. Cloud SQL モデルをクリックして、[Relations] タブに移動します。
  2. リレーションを作成するには、[Add Relation] をクリックします。作成ウィザードを使用して、次の操作を行います。

    1. もう一方のリレーション エンドのターゲット モデルを設定します。
    2. 各リレーション エンドのカウントを選択します。
    3. (省略可)デフォルト値を使用しない場合は、各リレーション エンドの名前を入力します。
    4. (省略可)1 対 1 または 1 対多のリレーションの場合、カウントが One のリレーション エンドに Owner を選択します。次のすべての条件を満たす場合にのみ、リレーションに所有者モデルを指定します。
  3. [作成] をクリック

リレーションを作成したら、リレーション エンドの名前を編集できます。リレーション エンドのカウントが One の場合は、所有権を有効または無効にできます。リレーション エンドのカウントが Many の場合は、並べ替えの方法を変更できます。

リレーションを編集するには:

  1. モデルをクリックして、[Relations] タブに移動します。
  2. リレーションのリストで、リレーション エンドの名前をクリックします。

    2 つのモデルのレコードを関連付けているリレーションの場合、各モデルのリレーション リストには反対側のモデルのリレーション エンド名が表示されます。同じモデル内のレコードを関連付けているリレーションの場合は、両方のリレーション エンドが表示されます。EmployeeDB モデルの例では、ManagerMembers の両方が [Relations] タブに表示されています。

  3. 名前、所有者、または並べ替えを編集します。変更は自動的に保存されます。

    並べ替えを設定するには、レコードの並べ替えに使用するフィールドを選択します。[Ascending] チェックボックスをオンにして、リレーション エンドのレコードの並べ替え順を設定します。並べ替えの順序を指定しない場合、モデルのデータ バックエンドにより並べ替え順が決まります。

関連レコードの所有権

少なくとも 1 つのリレーション エンドのカウントが One の場合、いくつかのルールに従って所有者を指定します。所有者を設定すると、2 つのモデルの関連レコードに対して所有者間のリレーションが作成されます。

  • 所有権あり - ユーザーまたはアプリのロジックが所有者モデルからレコードを削除すると、関連する所有レコードがすべて削除されます。所有レコードが削除されても、所有者のレコードは削除されません。
  • 所有権なし - 一方のリレーション エンドのレコードを削除したときに、もう一方のリレーション エンドのレコードは削除されません。

次の両方の条件を満たしている場合にのみ、リレーションに所有者モデルを指定します。

  • 所有されているレコードに必ず所有者レコードが存在している。
  • 所有者レコードが削除されたときに、そのリレーション エンドのレコードも自動的に削除されるようにする。

所有権の例

請求書が削除されたときに請求書の明細も削除する場合、Invoice モデルと Item モデルの間には 1 対多のリレーションを設定し、Invoice モデルを所有者にします。これにより、ユーザーが Invoice レコードを削除したときに、所有されているすべての Item レコードが削除されます。削除される Invoice レコードに関連付けられていたレコードも削除されます。

削除されるレコードはアイテムの特定のインスタンス(在庫の特定のディスク ドライブなど)であり、アイテムのカテゴリ(在庫のあるディスク ドライブの種類など)ではありません。

所有権のルール

  • 所有者になれるのは、1 対 1 または 1 対多のリレーションの一方の側にあるモデルだけです。
  • 所有権に循環が生じる場合、モデルを所有者として指定できません(たとえば、レコード A がレコード B を所有し、レコード B がレコード A を所有する場合など)。
  • 所有者が所有するリレーションをつなぐことができます。たとえば、次のモデルとリレーションがあるとします。

    • ForumTopicComment モデル
    • Forum から Topic への 1 対多のリレーションで、Forum モデルが所有者
    • Topic から Comment への 1 対多のリレーションで、Topic モデルが所有者

    Topic レコードを削除すると、App Maker は関連する Comment レコードをすべて削除します。Forum レコードを削除すると、App Maker は関連する Topic レコードをすべて削除し、それに関連する Comment レコードもすべて削除します。

  • 複数のリレーションを持つモデルは、複数の所有者モデルで所有できます。

  • 所有者モデルからレコードを削除すると、他のモデルのレコードに所有されているかどうかに関係なく、App Maker はそのレコードが所有するレコードを他のモデルから削除します。

レコード間の関連付けの管理

関連付けは、モデルのリレーションによる 2 つのレコード間のリンクを表します。たとえば、リレーション エンド ManagerTeams の間に 1 対多のリレーションがある場合、Manager1 のレコードと各チームのレコードの間には関連付けが存在します。

アプリのワークフローに応じて、次の 3 つの方法でレコード間の関連付けを作成し、変更できます。

  1. データ バインディング。ウィジェットがレコードの関連付けの表示と変更を行います。
  2. クライアント スクリプト。データ バインディングよりも複雑な関連付けの変更を行う場合に使用します。
  3. サーバー スクリプト。変更を一括で行う場合や、安全に行う場合に使用します。

データ バインディングによる関連付けの変更

データ バインディングでレコード間の関連付けを変更する場合、モデル データソースの item プロパティを使用してリレーション エンドにアクセスするのが最も簡単な方法です。モデル データソースでは、リレーション エンドはフィールドと同じようにレコード プロパティとして公開されます。

ウィジェットの表示を有効にする場合や、現在選択されているレコードの関連レコードを変更する場合は、ウィジェットの value@datasource.item.[relation end name] にバインドします。この方法は、プルダウン ウィジェット(リレーション エンドのカウントが One の場合)や複数選択ボックス(リレーション エンドのカウントが Many の場合)に特に便利です。たとえば、データモデルへの接続チュートリアルで、従業員の一覧を表示する UI 要素を作成するときに、ウィジェット値とデータソースのバインディングを設定します。

クライアント スクリプトによる関連付けの変更

この方法では、データソースにレコードの関連レコードが読み込まれていることを確認する必要があるため、データ バインディングよりも複雑になります。関連レコードの読み込みは次の方法で確認します。

  • データソースのプリフェッチを有効にする。
  • レコード_loadRelation-name を呼び出し、非同期コールバックを待機する
  • リレーション データソースの onLoad イベントを待機する。
  • リレーション データソースを使用するウィジェットの onDataLoad イベントを待機する。

たとえば、以前の EmployeeDB - Team リレーションのシナリオの場合、次のコードを使用してレコードを関連付けることができます(マネージャーをチームメンバーに割り当て、チームメンバーをマネージャーのチームに追加します)。このシナリオでは、正しい従業員レコードに簡単にアクセスできるように、EmployeeDB モデルに次の 2 つのデータソースを作成しました。

  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 モデルのフィールドでレコードのフィルタリングや並べ替えを行うには、1 つまたは複数のリレーション名を追加し、その後にフィールド名を追加します。たとえば、関連レコードの Age フィールドで Mother リレーションをフィルタリングするには、Mother.Age を使用します。

関連付けられているレコードまたはレコードキーに equalsnotEqualsinnotIn フィルタを適用することもできます。たとえば、マネージャーの上司が正しく割り当てられていることを確認するには、Manager.Manager._key._equals でフィルタリングします。

リレーションのフィルタリングは、データ バインディングサーバー スクリプトで使用できます。

関連情報