はじめに
こんにちは
必要に迫られてドキュメント型DBの1つであるMongoDBを触らなければならない機会があったのでその共有(今頃?w)
Go言語を例にMongoDBで簡単なAPIをつくってみたいと思います。
MongoDBとのコネクション
ドライバーの導入
MongoDBは独自プロトコルを採用しているため、ドライバーを使う必要があります。
※今回はスター数からこちらのドライバーを使わせて頂くことにしました。
https://github.com/mongodb/mongo-go-driver
※導入方法のざっくりとした説明は前回の記事でまとめております。
https://qiita.com/leica19/items/ccdd2b452477b1ad7aed
Go言語からの接続
必要なパッケージはこちら
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
実コードはこの2行で完結します。
clientOptions := options.Client().ApplyURI("mongodb://db")
client, _ := mongo.Connect(context.TODO(), clientOptions)
ApplyURI()の引数にある「db」がhostとなりますが、今回はdocker-composeを利用しているため「db」という名前でアクセスすることができます。
見栄えよく関数化すると
func ConnectMongoDB() *mongo.Client {
clientOptions := options.Client().ApplyURI("mongodb://db")
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
return client
}
こんな感じでしょうか。
コレクションの作成
次にコレクションを作成する必要があります。
※コレクションとはドキュメントの集合単位です。
コレクションの作成にはmongo.ClientのCollectionメソッドが使えます。
戻り値としてmongo.Collectionのハンドラーが返ってきます。
※今後は主にこのハンドラーを使ってコレクションを操作していくことになります。
collection := client.Database("test").Collection("users")
今回は"users"という名前のコレクションを作成しています。
ドキュメントの新規作成
POSTのエンドポイントを経由してusersコレクションに新規ドキュメントを登録してみます。
JSONをPOSTできるようにします。
以下、ルーティングとハンドラー
e.POST("/user", func(c echo.Context) error {
jsonBody := echo.Map{}
if err := c.Bind(&jsonBody); err != nil {
errorResponse := ErrorResponse{Message: "Bad Request"}
return c.JSON(http.StatusBadRequest, errorResponse)
}
result, _ := collection.InsertOne(context.TODO(), jsonBody)
response := Response{ID: result.InsertedID}
return c.JSON(http.StatusOK, response)
})
リクエストのBodyパラメーターをc.Bind()でGo言語のmapにマッピングしております。
※Web frameworkとしてEchoを使っています。https://echo.labstack.com/guide
レコードの新規作成には、InsertOneメソッドを利用しています。
さっそく登録してみます。
レスポンスにはドキュメントのIDであるObjectIdを返しています。
ドキュメントの参照
続いて、先ほど登録したドキュメントがきちんと登録されているかGETリクエストで確認してみます。
ハンドラーから
e.GET("/user/:_id", func(c echo.Context) error {
raw_id := c.Param("_id")
_id, _ := primitive.ObjectIDFromHex(raw_id)
result := echo.Map{}
if err := collection.FindOne(context.TODO(), bson.M{"_id": _id}).Decode(&result); err != nil {
errorResponse := ErrorResponse{Message: "Not Found"}
return c.JSON(http.StatusNotFound, errorResponse)
}
return c.JSON(http.StatusOK, result)
})
ポイントは、primitiveパッケージのObjectIDFromHex関数を使って、
16進数の文字列できたObjectIdを正しいObjectIdに変換する処理を挟むところです。
※内部的なことはよくわかってません。すみません。
ObjectIdをリクエストパスに入れてGETすると
先ほどPOSTしたJSONが正しく返ってきています。
ドキュメントの削除
最後に削除です。
特に目立ったところはありませんが、ハンドラーは
e.DELETE("/user/:_id", func(c echo.Context) error {
raw_id := c.Param("_id")
_id, _ := primitive.ObjectIDFromHex(raw_id)
result, _ := collection.DeleteOne(context.TODO(), bson.M{"_id": _id})
return c.JSON(http.StatusOK, result)
})
仮実装なので、DeleteOneメソッドの戻り値をそのままレスポンスしています。。
リクエストパスにObjectIdを入れて、DELETEメソッドでリクエストすればドキュメントが削除されます。
一応GETでも確認
きちんとドキュメントが削除されています。
最後に
今回は非常にあっさりしたものですが、今後はmongoのクエリにも詳しくなりたいな。というかならなくちゃ。
読んで頂き、ありがとうございました。
今回のソースコードはこちらで公開しております。
https://github.com/leica19/go-mongo-sample-api
参考
-
MongoDB公式チュートリアル
-
公式APIドキュメント