ent勉強メモ
GoのORMのentを勉強したときのメモが手元で眠っていたのでとりあえず公開。PostgreSQL on Docker でローカル開発したコードもそのうち公開したい。
いい感じの記事がすでにあった
- go generateした時点でDBへ接続して操作するAPIが用意される
- 接続先のDBさえありさえすればGoogle DriveからSDKのAPIを使って情報を引き出すとかの操作をするだけ、特に身構えて考えすぎる必要はなさそう
Quick Introduction
- entはシンプルかつ強力なGoのエンティティフレームワーク
- 大きいデータモデルを持つアプリケーションの構築と保守を簡単にする
- 次の原則を守る
- データベーススキーマをグラフ構造として簡単にモデル化する
- Goのコードとしてスキーマを定義する
- コード生成に基づいた静的な型付け
- データベースのクエリとグラフのトラバーサルの記述が容易
- Goのテンプレートを使って拡張とカスタマイズが簡単
Setup A Go Environment
go mod init entdemo
Create Your First Schema
- プロジェクトの直下で
go run -mod=mod [entgo.io/ent/cmd/ent](http://entgo.io/ent/cmd/ent) new User
- このコマンドは
entdemo/ent/shcema
ディレクトリの下にUser
のスキーマを生成する- フィールドを2つ追加してプロジェクトのルート直下で
go generate ./ent
を実行
- フィールドを2つ追加してプロジェクトのルート直下で
Create Your First Entity
-
Client
を作成してスキーママイグレーションを実行、エンティティとやりとりする - スキーママイグレーションを実行後、CreateUserという関数でユーザを作成する
Query Your Entities
- entは各エンティティスキーマのパッケージを生成する
- パッケージには述語、デフォルト値、バリデータ、ストレージ要素に関する追加の情報(列名・プライマリーキーなど)
Add Your First Edge (Relation)
- チュートリアルのこのパートでは、スキーマにおける別エンティティへのエッジ(リレーション)を宣言したい
- CarとGroupの2つのエンティティを追加しましょう。ent CLIで初期スキーマを生成し、手動でフィールドを追加します
- 最初のリレーションを定義しましょう。ユーザが一つ以上のカーを持つが、カーは一人のみのオーナーしか持たないということを定義するUserからCarへのエッジ(1対多リレーション)
- ユーザスキーマにcarsエッジを追加し、
go generate ./ent
を実行しましょう - 2つカーを作成しユーザに追加します
- carsエッジ(リレーション)をクエリする方法
Add Your First Inverse Edge (BackRef)
- Carオブジェクトがあり、このカーを所有するユーザであるオーナーを取得したいと仮定します
- inverse edgeと呼ばれる別の種類のエッジが使え、
edge.From
関数を使って定義されます - memo)このパートの絵はUserから見て多数のCarがあり得るので矢印の方向はUserからCarで、User1つに多数のCarなので矢印の始点に1、終点にM
- 逆エッジはCarから見て1つのUserが存在して多数のCarに一つのUserがあるので始点にM、終点に1と見ると良さそう?
- そしてそれぞれのエッジ(リレーション)に適切な名前が振られているイメージだろうか
- 図の新しいエッジは半透明でデータベース上では別のエッジを作らないことを強調します
- 実際のエッジ(リレーション)へのただのback-referenceです
- what is back-reference in database
- Carスキーマにownerという名前の逆エッジを追加して、Userスキーマのcargsエッジに参照させ、
go run generate ./ent
を実行します- carsはUserスキーマでedge.Toで定義、ownerはCarスキーマでedge.Fromで定義しRefにcarsを指定
- 逆エッジをクエリする(Carを全件取得、CarからOwenrをクエリしてユーザを引く)
Visualize the Schema
- ここまででスキーママイグレーションの実行といくつかのエンティティの作成に成功しました
- データベースのためにEntを使って生成されたSQLスキーマを表示するにはAtlasをインストールして次のコマンドを実行します
Create Your Second Edge
- ユーザとグループ間の多対多リレーションを作ります
- 各グループは多数のユーザを持ちユーザも多数のグループに結びつけられます
- 図ではGroupスキーマはusesエッジ(リレーション)の所有者でUserエンティティはgropusという名前のこのリレーションへのback-reference or inverse edgeを持ちます
Run Your First Graph Traversal
- 最初のグラフトラバーサルを実行するためにいくつかのデータ(ノードとエッジ、つまりエンティティとリレーション)を生成する必要があります
- フレームワークを使って図のグラフを作成しましょう
- データを持つグラフができたら、それに対するクエリを実行できます
- GitHubグループ内の全ユーザのカーを取得する
- 上記のクエリを変更し、トラバーサルのソースがユーザーArielになるようにします
- ユーザーを持つすべてのグループを取得する(ルックアサイド述語を持つクエリー)
Schema Migration
- 自動マイグレーション
- バージョン付けされたマイグレーション
Home > Schema > Introduction
https://entgo.io/docs/schema-def/#:~:text=Schema describes the definition of,%2C or User 's friends.
- スキーマはグラフにおける一つのエンティティの型の定義を記述する(e.g. User)
- 次のコンフィグレーションを含む
- エンティティフィールド(プロパティ)(Userの名前や年齢)
- エンティティエッジ(リレーション)(ユーザーのグループ、友達)
- つまり、別エンティティとの繋がり?年齢や名前は別エンティティでなさそう
- データベースの特定のオプション(インデックス、ユニークインデックス)
- エンティティスキーマは通常プロジェクトのルート直下
ent/shcema
の中に格納され、次のentc
で生成されるgo run -mod=mod [entgo.io/ent/cmd/ent](http://entgo.io/ent/cmd/ent) new User Group
-
Client
のようなスキーマ名は内部で使われているため利用できないが、予約された名前はアノテーションを使って避けることができる
gRPCサーバ with ent
- Entはent/contribで利用可能なプラグインを使って、スキーマからのgRPCサービスの自動生成をサポート
-
entproto
というコマンドライン(またはコード生成フック) は、entスキーマからProtocol Buffer定義とgRPCサービス定義を生成するために使用されます。 スキーマは、ドメイン間のマッピングを支援するためにentproto
アノテーションを使用してアノテーションされます。 - protoc(protobuf compiler)プラグインの
protoc-gen-entgrpc
は、データベースからの読み書きにプロジェクトのent.Client
を使用するentproto
によって生成されたgRPCサービス定義の実装を生成するために使用されます - 生成されたサービス実装を組み込むgRPCサーバー自体は、開発者が書きます
セットアップ
- スキーマ初期化→スキーマ定義→go generate
- →
entproto
パッケージをgo get - この時点でDBへ接続してマイグレーションを実行してテーブル作成しデータの読み書きが可能になる
- テーブル名はどこで決まる?
entprotoでProtobufを生成する
-
entproto
でProtobuf定義を生成するためにスキーマにアノテーションを付与が必要entproto.Message()
-
entproto.Field()
protobufのメッセージタイプのフィールドの番号 - protobufメッセージタイプ定義の生成のために
ent/generate.go
にentproto
コマンドラインツールを呼び出すgo:generate
ディレクティブを追加 - →go generateで生成
gRPCサービスの生成
- DBからエンティティを作成・読み取り・更新・削除できる実際のgRPCサーバがゴール
-
entproto.Service()
をスキーマにアノテートすると実装を生成してくれる - →go generate
- memo)
- twilio-ai-telphone-database-protoのリポジトリでこれをやる?
- ここまででDBへの操作のサービスの実装が出来上がる
サーバーとクライアントの作成
- ent側では自動生成しない
残りのトピック
エッジの使い方
Option Fileds
Configuring Service Method Generation
Working with External gRPC Services
Ent で完全に動作する Go gRPC サーバーを2分で生成する | ent
entを利用したプロジェクトにgRPCのサーバを生やしてみた|すずき
- フィールド番号は2から始まる
field.UUID
- 他に数ページある
entのProtocol BuffersスキーマとgRPCサービスのコード生成機能を試したみた
Golang / Gin + Ent. でRest APIを作成するハンズオン
GolangにORM導入(ent migration編) - Qiita
100%型安全なgolangORM「ent」を使ってみた | フューチャー技術ブログ
ent で PostgreSQL に接続できるか|PostgreSQL と ORM と Logging と
GoのFacebook製ORM"ent"を使ってみた - SMARTCAMP Engineer Blog
- go get -u entgo.io/contrib/entproto@master
ent でスキーマを設計する|PostgreSQL と ORM と Logging と
- そもそもエッジって何
- スキーマにおけるフィールド(あるいはプロパティ)はノードの属性です
- 例:Userはage,name,username, created_atのフィールドを持つ
- フィールドはFieldsメソッドでスキーマから返されます
- すべてのフィールドはデフォルトで必須
- Optionalメソッドを使ってオプショナルに設定できる
- entによって現在サポートされている型
- int,unit8,float64などGoの数値型、bool,string
- time.Time,UUID
- bytes,JSON,Enum,Other (SQL only)
- 各型がデータベースの型にどうマッピングされるかはMigrationセクションを参照
- IDフィールド
- idフィールドはスキーマにビルドインされており宣言の必要はありません
- SQLベースドなデータベースでは、型はデフォルトでint(codegen optionで変更可能)でデータベース上でオートインクリメントです
- 全てのテーブルでidフィールドをユニークに設定するには、スキーマ・マイグレーションを実行時、WIthGlobalUniqueIDオプションを使います
- idフィールドに対して異なる設定が必要な場合やidの値がアプリケーショによるエンティティの作成時に付与されるべき場合(e.g. uuid)、ビルトインのid設定をオーバーライドしてください
- IDを生成するためにカスタム関数を設定する必要がある場合はDefaultFuncを使ってリソースの生成時に必ず実行される関数を指定できます
- Database Type
- SchemaType:データベース方言とGoのタイプのマッピングを上書きする
- Go Type
- Filedのデフォルト型はGoの基本型、GoTypeで上書きできる
- Other Filed
- フィールドの標準型以外の型
- DefaultValues
- ユニークでないフィールドはDefaultやUpdateDefaultメソッドでデフォルト値をサポートする
- entsql.Annotations:SQL固有のリテラルや関数呼び出しのような式をデフォルト構成に追加できる
- DefaultFuncがエラーを返す場合はschema-hooksで適切に処理すべき
- Validators
- エンティティが作成・更新される前にフィールドの値に適用される関数を定義できる
- Built-in Validators
- Optional
- エンティティ生成時に必須でないフィールド
- データベース上でnullableフィールドにセットされる
- エッジと異なりフィールドはデフォルトで必須でオプショナルへの設定はOptionalメソッドで明示的に行う
- Nillable
- フィールドのゼロ値とnilを区別したいような場合
- よくわからず、とりあえず何らかの値が必要かnilもOKかくらいの気持ち
- Immutable
- エンティティ作成時のみセット可能なフィールド
- 更新ビルダーにセッター生成されない
- Uniqueness
- ユニークとしてフィールドを定義する、デフォルト値もてない
- Comments
- Storage Key
- カスタムストレージ名、SQLの列名にマッピングされる
- Indexes
- フィールドの組み?
- Struct Tags
- struct tagを追加できる
- このオプションを付与していない場合か付与していてjsonタグを含まない場合、デフォルトでjsonタグがフィールド名で追加される
- Additional Struct
- 命名規則
- フィールド名はsnake_case
- entによって生成される構造体のフィールド名にPascalCaseを使ってくれる?
ent ( entgo.io/ent ) で ULID を使う
はじめに|PostgreSQL と ORM と Logging と
Automatic migration planning
- https://entgo.io/ja/docs/versioned/auto-plan
- 自動マイグレーションの便利な特徴の一つは開発者がデータベーススキーマを作成・修正するのにSQLステートメントを書く必要がないこと
- 同様の利点を得るためにスキーマ偏向に基づいて、マイグレーションファイルを自動的に計画するスクリプトをプロジェクトに追加する
ent を利用している project の migration に atlas を使ってみる - Techtouch Developers Blog