こんにちは、Golangの記事第三弾です。
今回は Golang + MongoDB を使用する機会がありましたので、さっそく調べてみました!
ここでは、MongoDBの簡単な概要と、MongoDBの公式ドライバを使用した簡単なCRUD操作について見ていきます。
今回はReadとCreateのみ紹介ですが、公式のUsageから他も同様に確認できます。
MongoDB
MongoDBは、NoSQLのうち、ドキュメント指向のデータベースです。
RDBMSとの大きな違いとして、テーブルのように事前にデータ構造を決定しておかなくてもよい点などが挙げられます。
あとから自由にスキーマを変更できるので、APIの仕様変更などがあっても柔軟に対応できるようになっています。
シンプルで自由度の高いデータ構造も、静的型付けのGolangとは相性が良いように思います。
ドライバのインストール
公式のドキュメントを参考にします
https://docs.mongodb.com/drivers/go/current/quick-start/
go get go.mongodb.org/mongo-driver/mongo
接続の例
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
// Connection URI
const uri = "<<mongoDB-URI>>"
func main() {
// Create a new client and connect to the server
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}
defer func() {
if err = client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}()
// Ping the primary
if err := client.Ping(context.TODO(), readpref.Primary()); err != nil {
panic(err)
}
fmt.Println("Successfully connected and pinged.")
}
ドキュメントの取得
FindOne
type respData struct {
Id primitive.ObjectID `json:"id" bson:"_id"`
Name string `json:"name" bson:"name"`
}
func main() {
coll := client.Database("<<dbName>>").Collection("<<collectionName>>")
var result respData
err = coll.FindOne(context.TODO(), bson.D{{"<<fieldName>>", "hoge"}}).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
// This error means your query did not match any documents.
return
}
panic(err)
}
}
collection.FindOneの返り値は*mongo.SingleResultの型ですが、
Decodeが構造体にマッピングしてくれます。
Find (Multiple Documents)
type respData struct {
Id primitive.ObjectID `json:"id" bson:"_id"`
Name string `json:"name" bson:"name"`
}
func main() {
coll := client.Database("<<dbName>>").Collection("<<collectionName>>")
filter := bson.D{{"<<fieldName>>", bson.D{{"$eq", "hoge"}}}}
cur, err := coll.Find(context.TODO(), filter)
if err != nil {
panic(err)
}
for cur.Next(context.TODO()) {
var res respData
cur.Decode(&res)
fmt.Println(res)
}
}
複数ドキュメントの取得ができるFindは返り値が*mongo.Cursorです。
こちらもDecodeでマッピング可能。
ドキュメントの追加
InsertOne
func main() {
coll := client.Database("<<dbName>>").Collection("<<collectionName>>")
doc := bson.D{{"title", "Record of a Shriveled Datum"}, {"text", "No bytes, no problem. Just insert a document, in MongoDB"}}
result, err := coll.InsertOne(context.TODO(), doc)
if err != nil {
panic(err)
}
}
InsertMany
docs := []interface{}{
bson.D{{"title", "Record of a Shriveled Datum"}, {"text", "No bytes, no problem. Just insert a document, in MongoDB"}},
bson.D{{"title", "Showcasing a Blossoming Binary"}, {"text", "Binary data, safely stored with GridFS. Bucket the data"}},
}
result, err := coll.InsertMany(context.TODO(), docs)
if err != nil {
panic(err)
}
おわりに
MongoDBの操作について簡単にまとめてみました。
MongoDBは、bsonなど独特なデータ構造を使用する、RDBMSのような高度な結合処理が難しい、などわかりにくい部分もありましたが
Golang + MongoDB の組み合わせでは、高速な検索や柔軟なスキーマ変更など、開発に便利な感触がありました。
Aggregationなど高度な操作も、機会があればまとめたいと思います。
ありがとうございました。
備考
bson
- “Binary JSON,” の略
- https://www.mongodb.com/json-and-bson
高度な結合処理が難しい
- Joinに相当する機能としてAggregationが用意されています。
- https://docs.mongodb.com/manual/aggregation/