LoginSignup
11
0

はじめに

 この記事ではGo言語のBun ORMを使用している際に、マルチテナントに対応する方法を説明する記事です。BunのGitHubにはexampleとしてmulti-tenantが示されていますが、ドキュメントには詳しくはされていません。
 この記事ではGitHubの例をベースにマルチテナントを実装可能になることを目標とします。

解説

公式ではマルチテナント以外の部分も合わせてModel and query hooksとして示されています。
https://bun.uptrace.dev/guide/hooks.html

公式例

 公式が示しているexampleはGitHubから見ることが可能です。
https://github.com/uptrace/bun/tree/master/example/multi-tenant
 ただ、READMEを見ていただければ分かる通り、実装内容の解説は行われていません。コードの必要な箇所を抜粋しつつ解説を行っていきます。

Struct

 例で示されてるStructは次のとおりです。

story.go
type Story struct {
	ID       int64 `bun:",pk,autoincrement"`
	Title    string
	AuthorID int64
}

multi-tenant

 実際にマルチテナントの実装箇所は次の部分です。

main.go
var _ bun.BeforeSelectHook = (*Story)(nil)

func (s *Story) BeforeSelect(ctx context.Context, query *bun.SelectQuery) error {
	if id := ctx.Value("tenant_id"); id != nil {
		query.Where("author_id = ?", id)
	}
	return nil
}

 まずは、最初の行のvar _ bun.BeforeSelectHook = (*Story)(nil)では、Story Structに対しメインのクエリを発行する前にクエリをフックさせるためのものです。

 実装方法としては、実装したいStructに対し、メソッドとして実装します。引数にはcontext.Context*bun.SelectQueryを指定します。返り値にはerrorを指定します。

 あとは、実行したいクエリを*bun.SelectQueryのWhereメソッドなどで実装していく形になります。

その他

今回の例ではSelectQueryですが、InsertQueryなどでも実装可能です。また、AfterSelectなど、メインのクエリの後に実装することも可能です。もちろん、どちらも実装することもできます。

11
0
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
11
0