非关系型数据库 sql
关系型数据库:MySQL
,PgSQL
:一致性保证,支持事务
no-sql
非关系型数据库:Redis
,MongoDB
,ElasticSearch
,事务能力不强
MongoDB
:可记录json
文档,丰富的查询能力,serveless
宠儿
安装 学习使用,在k8s
上安装单机版即可。集群版本待补充。
yaml
文件:使用本地存储,有状态的方式部署,通过configmap
注入配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # cat configMap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mongodb-conf data: mongodb.conf: | dbpath=/data/middleware-data/mongodb logpath=/data/middleware-data/mongodb/mongodb.log pidfilepath=/data/middleware-data/mongodb/master.pid directoryperdb=true logappend=true bind_ip=0.0.0.0 port=27017
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # cat Service.yaml kind: Service apiVersion: v1 metadata: labels: name: mongodb name: mongodb spec: type: NodePort ports: - name: mongodb port: 27017 targetPort: 27017 nodePort: 30002 selector: name: mongodb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 # cat StatefulSet.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: mongodb spec: replicas: 1 serviceName: mongodb selector: matchLabels: name: mongodb template: metadata: labels: name: mongodb spec: containers: - name: mongodb image: mongo:4.2.1 command: - sh - -c - "exec mongod -f /data/middleware-data/mongodb/conf/mongodb.conf" imagePullPolicy: IfNotPresent ports: - containerPort: 27017 name: mongodb protocol: TCP volumeMounts: - name: mongodb-config mountPath: /data/middleware-data/mongodb/conf/ - name: data mountPath: /data/middleware-data/mongodb/ volumes: - name: mongodb-config configMap: name: mongodb-conf - name: data hostPath: path: /data/middleware-data/mongodb/
1 2 3 kubectl create -f configMap.yaml kubectl create -f Service.yaml kubectl create -f StatefulSet.yaml
简单学习增删改查,更加详细的操作和功能可查看官方文档:MongoDB中文手册|官方文档中文版
CRUD 创建数据库,如果数据库存在,则使用该数据库
创建集合(表),插入数据的时候会自动创建集合
增加一个数据
1 2 3 db.bookinfo.insertOne( {open_id:"1"} )
增加多个数据
1 2 3 4 5 6 7 8 9 db.bookinfo.insertMany([{ open_id:"1", _id:"5", login_count: 0, },{ open_id:"2", _id:"6", login_count: 2, }])
如果没有_id字段,会被自动分配一个字段
1 2 3 4 5 6 7 8 9 10 11 12 13 db.study1.insertOne({ a: 1 }) { "_id": {"$oid": "62c659ecc15c1f1f67acce55"}, "a": 1 } 系统分配的_id可以通过ObjectId搜索 db.study1.find({ _id : ObjectId("62c659ecc15c1f1f67acce55") })
删除集合
查询,返回数组
1 2 3 4 5 db.bookinfo.find() // 查询所有 db.bookinfo.find({ // 按条件查找 login_count : 0, })
删除数据
1 2 3 db.bookinfo.deleteOne({ _id: "2" })
更新,查找更新,非原子性
1 2 3 4 5 6 7 db.bookinfo.updateOne({ _id: "4" },{ $set: { login_count : 5 } })
原子操作加1
1 2 3 4 5 6 7 db.bookinfo.updateOne({ _id: "4" },{ $inc: { login_count : 1 } })
查询支持条件判断和嵌套结构体查找
创建索引
1 2 3 db.bookinfo.createIndex({ "login_count": 1 // login_count 从小到大创建索引,升序 })
Golang 操作MongoDB 官方文档:MongoDB Go Driver
import
1 2 3 go get go.mongodb.org/mongo-driver/mongo go get go.mongodb.org/mongo-driver/mongo/options go get go.mongodb.org/mongo-driver/mongo/readpref
连接
1 2 3 c := context.Background() client, err := mongo.Connect(c, options.Client().ApplyURI( "mongodb://192.168.41.249:30002/userinfo?readPreperence=primary&ssl=false"))
设置操作的database
和collection
1 col := client.Database("userinfo").Collection("userinfo")
增加 1 2 3 one, err := col.InsertOne(c, bson.M{ "user_id": "1001", })
返回ObjectID
1 fmt.Printf("one: %+v\n", one.InsertedID) // ObjectID("62c6e84d601444ae1c1d3c5e")
批量增加
1 2 3 4 5 6 7 8 9 result, err := col.InsertMany(c, []interface{}{ bson.M{ "user_id": "1002", }, bson.M{ "user_id": "1003", }, }) fmt.Printf("%+v\n", result.InsertedIDs) // [ObjectID("62c6e84d601444ae1c1d3c5f") ObjectID("62c6e84d601444ae1c1d3c60")]
查询 查询一个
1 2 3 4 5 6 7 8 9 find := col.FindOne(c, bson.M{ "user_id": "1002", }) u := struct { ID primitive.ObjectID `bson:"_id"` UserID string `bson:"user_id"` }{} find.Decode(&u) fmt.Printf("u: %+v\n", u) {ID:ObjectID("62c6e84d601444ae1c1d3c5f") UserID:1002}
查询多个
1 2 3 4 5 6 7 var us []UserInfo if err = cur.All(c, &us); err != nil { panic(err) } for _, user := range us { fmt.Println("user: ", user) // {ObjectID("62c6eb95a769d52ef97a53b4") 1001} }
删除 1 2 3 4 5 // delRes, _ := col.DeleteOne(c, bson.M{ // 删除一个 delRes, _ := col.DeleteMany(c, bson.M{ // 删除多个 "user_id": "1001", }) fmt.Printf("delete res: %+v", delRes) // {DeletedCount:1}
更新 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // updateOne, _ := col.UpdateOne(c, bson.M{ // 更新一个 updateMany, _ := col.UpdateMany(c, bson.M{ // 批量更新 "user_id": "1002", }, bson.M{ "$set": bson.M{ "name": "mitaka", }, }) // 判断是否有更新 if updateMany.MatchedCount != 0 { fmt.Println("matched and replaced an existing document") return }
常用场景 验证用户是否已经注册,如果注册,则返回这个用户的ObjectID
,如果没有注册,则创建用户,并且返回ObjectID
1 2 3 4 5 6 7 8 9 10 11 opts := options.FindOneAndUpdateOptions{} opts.SetUpsert(true) opts.SetReturnDocument(options.After) filter := bson.M{"user_id": "1013"} update := bson.M{"$set": filter} result := col.FindOneAndUpdate(c, filter, update, &opts) res := struct { ID primitive.ObjectID `bson:"_id"` }{} result.Decode(&res) fmt.Printf("res %+v", res)