Background

AWS Document DB是基本兼容Mongo DB的AWS服务,Mongo DB是比较流行的非结构化文档数据库。使用Golang操作Document DB的方法和操作Mongo DB的方法基本相同,用的也是mongo官方提供的package。

Code

  1. 连接数据库

假设我们已经在AWS Console中建立好了一个Document DB,数据库名字为demodb,并已经设置好了用户和密码。连接数据库的时候,需要用ssl方式作为authentication,所以我们 首先需要下载aws的ssl certificate文件:

wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem

下载之后,新建一个go文件保存证书的内容,例如在util目录下创建cert.go,内容如下:

package util
const CERT=`-----BEGIN CERTIFICATE-----
xxx
-----END CERTIFICATE-----`
`

以方便程序中调用。

编写连接数据的部分:

var Conn *mongo.Database

const (
	// Timeout operations after N seconds
	connectTimeout = 10
	// Which instances to read from
	readPreference           = "secondaryPreferred"
	connectionStringTemplate = "mongodb://%s:%s@%s/sample-database?ssl=true&replicaSet=rs0&readpreference=%s"
)

func InitDB() error {
	clusterEndpoint := os.Getenv("DOC_DB_HOST")
	username := os.Getenv("DOC_DB_USER")
	password := os.Getenv("DOC_DB_PASS")
	database := os.Getenv("DOC_DB_NAME")
	connectionURI := fmt.Sprintf(connectionStringTemplate, username, password, clusterEndpoint, readPreference)

	tlsConfig, err := getCustomTLSConfig()
	if err != nil {
		log.Fatalf("Failed getting TLS configuration: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	client, err := mongo.Connect(ctx, options.Client().ApplyURI(connectionURI).SetTLSConfig(tlsConfig))
	if err != nil {
		log.Fatalf("Failed to connect to cluster: %v", err)
	}
	err = client.Ping(context.TODO(), nil)
	if err != nil {
		log.Fatal(err)
	}
	Conn = client.Database(database)
	return err
}

func getCustomTLSConfig() (*tls.Config, error) {
	tlsConfig := new(tls.Config)
	certs := []byte(util.CERT)

	tlsConfig.RootCAs = x509.NewCertPool()
	ok := tlsConfig.RootCAs.AppendCertsFromPEM(certs)

	if !ok {
		return tlsConfig, errors.New("Failed parsing pem file")
	}

	return tlsConfig, nil
}
  1. 选择表
coll := Conn.Collection("demo")
  1. 定义表结构

接下来就可以操作数据库中的Collection了,假设我们创建一个叫做demo的表,首先定义表结构的struct:

type Demo struct {
	ID        primitive.ObjectID `bson:"_id" json:"id,omitempty"`
	Title     string             `bson:"title" json:"title"`
	Body      string             `bson:"body" json:"body"`
	CreatedAt time.Time          `bson:"created_at" json:"created_at,omitempty"`
	UpdatedAt time.Time          `bson:"updated_at" json:"updated_at,omitempty"`
}

其中ID使用primitive包的方法自动生成。

  1. 插入数据:
record := Demo{}
record.ID = primitive.NewObjectID()
record.Title = "demotitle"
record.Body = "test content"
record.SessionId = "2"
record.CreatedAt = time.Now()
record.UpdatedAt = time.Now()

res, err := coll.InsertOne(context.Background(), record)
  1. 查询单条数据:
filter := bson.D{{"title", "demotitle"}}
var res Demo
e = coll.FindOne(context.TODO(), filter).Decode(&res)
  1. 查询多条数据:
filter := bson.D{{"title", "demotitle"}}
var res []Demo
cur,err := coll.Find(context.TODO(), filter)
err = cur.All(context.Background(), &res)
  1. 更新数据:
filter := bson.D{{"title", "demotitle"}}
update := bson.D{
    {"$set", bson.D{
        {"body", "demobody"},
    }},
}
 
_, e = coll.UpdateOne(context.TODO(), filter, update)
  1. 删除数据:
//clear all data of the collection
_, e = coll.DeleteMany(context.TODO(), bson.D{{}})

Conclusion

这里只是列出了使用Golang操作Document DB的一些简单操作,实际上在使用过程中,会涉及到一些复杂的查询,比如group by,order by,limit 等等,这时就需要用到aggragate方法,相对于SQL语句来说,会稍微复杂一些。