ent勉強メモ

# ent勉強メモ

GoのORMのentを勉強したときのメモが手元で眠っていたのでとりあえず公開。PostgreSQL on Docker でローカル開発したコードもそのうち公開したい。

いい感じの記事がすでにあった

https://zenn.dev/tkb/articles/d1e6e3b7d62051

- go generateした時点でDBへ接続して操作するAPIが用意される
    - 接続先のDBさえありさえすればGoogle DriveからSDKのAPIを使って情報を引き出すとかの操作をするだけ、特に身構えて考えすぎる必要はなさそう

## **Quick Introduction**

[Quick Introduction | ent](https://entgo.io/ja/docs/getting-started/)

- 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` を実行

### Create Your First Entity

- `Client` を作成してスキーママイグレーションを実行、エンティティとやりとりする
- スキーママイグレーションを実行後、CreateUserという関数でユーザを作成する

### Query Your Entities

- entは各エンティティスキーマのパッケージを生成する
- パッケージには述語、デフォルト値、バリデータ、ストレージ要素に関する追加の情報（列名・プライマリーキーなど）

### Add Your First Edge (Relation)

- チュートリアルのこのパートでは、スキーマにおける別エンティティへのエッジ（リレーション）を宣言したい
- CarとGroupの2つのエンティティを追加しましょう。ent CLIで初期スキーマを生成し、手動でフィールドを追加します
- 最初のリレーションを定義しましょう。ユーザが一つ以上のカーを持つが、カーは一人のみのオーナーしか持たないということを定義するUserからCarへのエッジ（１対多リレーション）
- ユーザスキーマに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、終点に１と見ると良さそう？
    - そしてそれぞれのエッジ（リレーション）に適切な名前が振られているイメージだろうか
- 図の新しいエッジは半透明でデータベース上では別のエッジを作らないことを強調します
- 実際のエッジ（リレーション）へのただの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](https://entgo.io/docs/schema-def/#:~:text=Schema%20describes%20the%20definition%20of,%2C%20or%20User%20's%20friends).

- スキーマはグラフにおける一つのエンティティの型の定義を記述する(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` のようなスキーマ名は内部で使われているため利用できないが、予約された名前はアノテーションを使って避けることができる

[バージョン管理型マイグレーション | ent](https://entgo.io/ja/docs/versioned-migrations/)

## gRPCサーバ with ent

[gRPCの導入 | ent](https://entgo.io/ja/docs/grpc-intro/#)

- Entは[ent/contrib](https://github.com/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](https://entgo.io/ja/blog/2021/03/18/generating-a-grpc-server-with-ent/)

[entを利用したプロジェクトにgRPCのサーバを生やしてみた｜すずき](https://note.com/ryota_0624/n/n919d44501a3a)

- フィールド番号は2から始まる
- `field.UUID`
- 他に数ページある

[entのProtocol BuffersスキーマとgRPCサービスのコード生成機能を試したみた](https://zenn.dev/unm/articles/f73b2ae3a4b4c7)

- 

[Golang / Gin + Ent. でRest APIを作成するハンズオン](https://zenn.dev/dmorita00/scraps/9d7ecf8925064e)

[](https://medium.com/sprocket-inc/entのstoragekeyの使い所-インデックス名がpostgresqlの識別子の長さの上限を超えてインデックスを作成できない問題を回避する-aa4e5ef4107e)

[GolangにORM導入(ent migration編) - Qiita](https://qiita.com/kouji0705/items/a591aaec54b639a5dfac)

[100%型安全なgolangORM「ent」を使ってみた | フューチャー技術ブログ](https://future-architect.github.io/articles/20210728a/)

[ent で PostgreSQL に接続できるか｜PostgreSQL と ORM と Logging と](https://zenn.dev/spiegel/books/a-study-in-postgresql/viewer/connect-with-ent)

[GoのFacebook製ORM"ent"を使ってみた - SMARTCAMP Engineer Blog](https://tech.smartcamp.co.jp/entry/try-go-ent)

- go get -u [entgo.io/contrib/entproto@master](http://entgo.io/contrib/entproto@master)

[ent でスキーマを設計する｜PostgreSQL と ORM と Logging と](https://zenn.dev/spiegel/books/a-study-in-postgresql/viewer/entity-relationship-by-ent)

- そもそもエッジって何

[アノテーション | ent](https://entgo.io/ja/docs/schema-annotations/)

[Fields | ent](https://entgo.io/ja/docs/schema-fields/)

- スキーマにおけるフィールド（あるいはプロパティ）はノードの属性です
    - 例：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 を使う](https://zenn.dev/nazo/articles/37967d75677039)

[はじめに｜PostgreSQL と ORM と Logging と](https://zenn.dev/spiegel/books/a-study-in-postgresql/viewer/intro)

**Automatic migration planning**

- [https://entgo.io/ja/docs/versioned/auto-plan](https://entgo.io/ja/docs/versioned/auto-plan)
- 自動マイグレーションの便利な特徴の一つは開発者がデータベーススキーマを作成・修正するのにSQLステートメントを書く必要がないこと
- 同様の利点を得るためにスキーマ偏向に基づいて、マイグレーションファイルを自動的に計画するスクリプトをプロジェクトに追加する

[データマイグレーション | ent](https://entgo.io/ja/docs/data-migrations/)

[ent を利用している project の migration に atlas を使ってみる - Techtouch Developers Blog](https://tech.techtouch.jp/entry/ent-atlas-migration)

[entのDBマイグレーションを試みる｜すずき](https://note.com/ryota_0624/n/ndbe6daabbc25)

[100%型安全なgolangORM「ent」を使ってみた | フューチャー技術ブログ](https://future-architect.github.io/articles/20210728a/)

[Ent+Atlasでマイグレーションする](https://zenn.dev/renoinn/articles/3fb9d7cc4a0794)