4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Node.js向けORM Objection.jsを使ってみた(2) - Model定義について

Last updated at Posted at 2018-08-19

概要

Modelを定義する際は、Objection.jsのModelクラスを継承します。

const { Model } = require('objection');

class User extends Model {
  static get tableName() { return 'users'; }
  static get jsonSchema () {
    return {
      required: ['name', 'email'],
      properties: {
        id: { type: 'integer' },
        name: { type: 'string' },
        email: { type: 'string' }
      }
    };
  }

  static get relationMappings() {
    return {
      projects: {
        relation: Model.ManyToManyRelation,
        modelClass: Project,
        join: {
          from: 'users.id',
          through: {
            from: 'projectMembers.userId',
            to: 'projectMembers.projectId'
          },
          to: 'projects.id'
        }
      },
      tasks: {
        relation: Model.HasManyRelation,
        modelClass: Task,
        join: {
          from: 'users.id',
          to: 'tasks.assignedTo'
        }
      }
    };
  }
}

class Project extends Model {
  static get tableName() { return 'projects'; }
  static get jsonSchema () {
    return {
      required: ['name'],
      properties: {
        id: { type: 'integer' },
        name: { type: 'string' },
        ownerId: { type: 'integer' }
      }
    };
  }

  static get relationMappings() {
    return {
      members: {
        relation: Model.ManyToManyRelation,
        modelClass: User,
        join: {
          from: 'projects.id',
          through: {
            // projectMembersはjoinテーブル
            from: 'projectMembers.projectId',
            to: 'projectMembers.userId'
          },
          to: 'users.id'
        }
      },
      owner: {
        relation: Model.HasOneRelation,
        modelClass: User,
        join: {
          from: 'projects.ownerId',
          to: 'users.id'
        }
      },
      tasks: {
        relation: Model.HasManyRelation, 
        modelClass: Task,
        join: {
          from: 'projects.id',
          to: 'tasks.projectId'
        }
      }
    };
  }
}

class Task extends Model {
  static get tableName() { return 'tasks'; }
  static get jsonSchema() {
    return {
      required: ['name', 'projectId'],
      properties: {
        id: { type: 'integer' },
        name: { type: 'string' },
        description: { type: 'string' },
        assignedTo: { type: 'integer' },
        projectId: { type: 'integer' },
        deadline: { type: 'string' },
        createdAt: { type: 'string' },
        updatedAt: { type: 'string' }
      }
    };
  }

  static get relationMappings() {
    return {
      project: {
        relation: Model.BelongsToOneRelation,
        modelClass: Project,
        join: {
          from: 'tasks.projectId',
          to: 'projects.id'
        }
      },
      user: {
        relation: Model.BelongsToOneRelation,
        modelClass: User,
        join: {
          from: 'tasks.assignedTo',
          to: 'users.id'
        }
      }
    };
  }
}

staticプロパティ

Modelクラスには、validationや対応するテーブルの定義などに関するstaticプロパティやメソッドが定義されており、
Modelのサブクラスでoverrideすることによって、クエリ発行時の挙動などを変更できます。

tableName

必須

Modelに対応するテーブル名を文字列で設定します。

idColumn

省略可能(デフォルトは"id")

プライマリーキーの名前を文字列で指定します。

複合主キーの場合は、各キーの名前を格納した配列を指定します。

jsonSchema

省略可能

JSONSchemaに基づいて、バリデーションルールを定義します。

省略した場合は、バリデーションは実行されません。

relationMappings

省略可能

他のモデルとの関連を定義します。

Eager loadingやGraph inserts等の機能を使用する際に必要になります。

BelongsToOne

relationプロパティに、Model.BelongsToOneRelationを設定します。

class Task extends Model {
  ...
  static get relationMappings() {
    return {
      // 関連名。Eager loading等を使用した際に、インスタンスのプロパティ名として使用されます。
      project: {
        relation: Model.BelongsToOneRelation,
        // 参照先Modelのコンストラクタ または 参照先Modelをexportしているモジュールへの絶対パス
        modelClass: Project,
        join: {
          // 参照元テーブル.参照元カラム
          from: 'tasks.projectId',
          // 参照先テーブル.参照先カラム
          to: 'projects.id'
        }
      }
    };
  }
  ...
}

HasOne

class Project extends Model {
  ...
  static get relationMappings() {
    return {
      // 関連名。Eager loading等を使用した際に、インスタンスのプロパティ名として使用されます。
      owner: {
        relation: Model.HasOneRelation,
        // 参照先Modelのコンストラクタ または 参照先Modelをexportしているモジュールへの絶対パス
        modelClass: User,
        join: {
          // 参照元テーブル.参照元カラム
          from: 'projects.ownerId',
          // 参照先テーブル.参照先カラム
          to: 'users.id'
        }
      }
    };
  }
  ...
}

HasMany

class User extends Model {
  ...
  static get relationMappings() {
    return {
      // 関連名。Eager loading等を使用した際に、インスタンスのプロパティ名として使用されます。
      tasks: {
        relation: Model.HasManyRelation,
        // 参照先Modelのコンストラクタ または 参照先Modelをexportしているモジュールへの絶対パス
        modelClass: Task,
        join: {
          // 参照元テーブル.参照元カラム
          from: 'users.id',
          // 参照先テーブル.参照先カラム
          to: 'tasks.assignedTo'
        }
      }
    };
  }
  ...
}

ManyToMany

relationプロパティに、Model.ManyToManyRelationを設定します。

また、joinテーブルに関する定義を、join.throughプロパティに設定します。

class Project extends Model {
  ...
  static get relationMappings() {
    return {
      // 関連名。Eager loading等を使用した際に、インスタンスのプロパティ名として使用されます。
      projects: {
        relation: Model.ManyToManyRelation,
        // 参照先Modelのコンストラクタ または 参照先Modelをexportしているモジュールへの絶対パス
        modelClass: Project,
        join: {
          // 参照元テーブル.参照元カラム
          from: 'users.id',
          // joinテーブルに関する定義
          through: {
            from: 'projectMembers.userId',
            to: 'projectMembers.projectId'
          },
          // 参照先テーブル.参照先カラム
          to: 'projects.id'
        }
      }
    }
  }
  ...
}

参考

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?