🙄
mongo-go-driverの接続処理を関数オブジェクトを活用して共通化してみる
概要
GolangでMongoDBを使う時に入れるライブラリmongo-go-driverですが、RDBでベタでSQLを書くようなDBの接続処理を書かなければいけません。MongoDB.com公式Goドライバを使った基本操作の記事にあるように、コンテキストの生成・接続処理・deferによる切断処理、を書いていきその後にクエリを発行する形になります。
ただ、この一連の接続処理がクエリ毎に変わるわけではないので、どうにかして共通化してみようと考えてみて、実装の一例を書いてみます。なお、この記事はあくまで個人的に考えたものであるので、一般的にこの内容がベストであるかは定かではなく、あくまで参考までにして頂けると幸いです。
実装方針
- クエリについては関数オブジェクト(関数の値化のことを関数オブジェクトと言うものとする)で別途定義して、共通の実行処理に渡します。Golangで関数オブジェクトを使う方法はGo言語 - 無名関数を参照のこと。
- 共通のクエリ実行処理には、関数オブジェクトとコレクション名を渡します。
- 共通のクエリ実行処理の返り値は
[]bson.M
型固定とする。もしfind文で結果のデコードが必要な場合は、受け取った先でデコードを行うものとします。
実装例
- クエリの定義
querySample.go
func GetSample(param string) (sample.Result, error) {
// 共通処理に渡す関数
f := func(col *mongo.Collection) ([]bson.M, error) {
findOptions := options.Find()
findOptions.SetSort(bson.D{{Key: "date", Value: 1}})
filter := bson.D{{Key: "word", Value: "param"}}
cur, err := col.Find(context.Background(), filter, findOptions)
if err != nil {
return nil, err
}
var docs []bson.M
for cur.Next(context.Background()) {
var doc bson.M
if err = cur.Decode(&doc); err != nil {
return nil, err
}
docs = append(docs, doc)
}
return docs, nil
}
// 共通
queryResult, err := util.ExecuteDbQuery(f, "sample_collection")
if err != nil {
return nil, err
}
// 以下デコード処理・・・
}
- 実行処理
executeSample.go
func ExecuteDbQuery(queryFunc func(*mongo.Collection) ([]bson.M, error), colName string) ([]bson.M, error) {
// MongoDBの接続設定
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
c, _ := mongo.Connect(ctx, options.Client().ApplyURI(os.Getenv("DB_CONNECTION")))
defer c.Disconnect(ctx)
col := c.Database(os.Getenv("DB_NAME")).Collection(colName)
// 関数の呼び出し結果を返す
return queryFunc(col)
}
Discussion