Go操作MongoDB 1 . 简介 mongoDB 是目前比较流行的一个基于分布式文件存储 的数据库 ,它是一个介于关系数据库和非关系数据库(NoSQL)之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
2 . MongoDB介绍和部署 mongoDB 是目前比较流行的一个基于分布式文件存储的数据库,它是一个介于关系数据库和非关系数据库(NoSQL)之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
mongoDB中将一条数据存储为一个文档(document),数据结构由键值(key-value)对组成。 其中文档类似于我们平常编程中用到的JSON对象。 文档中的字段值可以包含其他文档,数组及文档数组。
2.1 MongoDB相关概念 mongoDB中相关概念与我们熟悉的SQL概念对比如下: 
MongoDB术语/概念 说明 对比SQL术语/概念 database 数据库 database collection 集合 table document 文档 row field 字段 column index index 索引 primary key 主键 MongoDB自动将_id字段设置为主键 primary key 
2.2 MongoDB本地安装 我们这里下载和安装社区版,官网下载地址 。 打开上述连接后,选择对应的版本、操作系统平台(常见的平台均支持)和包类型,点击Download按钮下载即可。
这里补充说明下,Windows平台有ZIP和MSI两种包类型: * ZIP:压缩文件版本 * MSI:可执行文件版本,点击”下一步”安装即可。
macOS平台除了在该网页下载TGZ文件外,还可以使用Homebrew安装。
更多安装细节可以参考官方安装教程 ,里面有Linux、macOS和Windows三大主流平台的安装教程。
安装 
# 创建mongo用户 useradd mongod echo 123  |passwd --stdin mongod # 创建目录结构 mkdir -p /mongodb/{conf,log,data,bin} # 解压软件到指定位置 tar xf mongodb-linux-x86_64-rhel70-3.4 .24 .tgz -C /mongodb/ cp -a /mongodb/mongodb-linux-x86_64-rhel70-3.4 .24 /bin 
启动 
mongod --dbpath=/opt/ data/apps/mongodb/data --logpath=/opt/ data/apps/mongodb/log/mongo.log --port=27017  --logappend --fork cat >> /etc/ security/limits.conf <<EOF * soft nproc 65530  * hard nproc 65530  * soft nofile 65530  * hard nofile 65530  EOF ulimit -n 65535  ulimit -u 20480  mongo	   
配置文件启动 
[mongod@client-1  mongodb]$ cat /opt/data/apps/mongodb/conf/mongo.conf dbpath=/opt/ data/apps/mongodb/data logpath=/opt/ data/apps/mongodb/log/mongo.log logappend = true  port=27017   fork=true   auth=true  #bind_ip = 127.0 .0 .1   journal=true   quiet=true  $ mongod -f /opt/data/apps/mongodb/conf/mongo.conf  mongod -f /opt/data/apps/mongodb/conf/mongo.conf --shutdown cat > /etc/ systemd/system/mongod.service <<EOF [Unit] Description=mongodb  After=network.target remote-fs.target nss-lookup.target [Service] User=mongod Type=forking ExecStart=/opt/ data/apps/mongodb/bin/mongod --config /opt/data/apps/mongodb/conf/mongo.conf ExecReload=/bin/ kill -s HUP $MAINPID ExecStop=/opt/ data/apps/mongodb/bin/mongod --config /opt/data/apps/mongodb/conf/mongo.conf --shutdown PrivateTmp=true    [Install] WantedBy=multi-user.target EOF systemctl start mongod systemctl stop mongod systemctl restart mongod 
2.3 Docker安装MongoDB 查看可用的 MongoDB 版本 
$ docker search mongo NAME                              DESCRIPTION                      STARS     OFFICIAL   AUTOMATED mongo                             MongoDB document databases ...   1989      [OK]        mongo-express                     Web-based MongoDB admin int...   22        [OK]        mvertes/alpine-mongo              light MongoDB container          19                   [OK] mongooseim/mongooseim-docker      MongooseIM server the lates...   9                    [OK] torusware/speedus-mongo           Always updated official Mon...   9                    [OK] jacksoncage/mongo                 Instant MongoDB sharded cluster  6                    [OK] mongoclient/mongoclient           Official docker image for  M...   4                    [OK] jadsonlourenco/mongo-rocks        Percona Mongodb with Rocksd...   4                    [OK] asteris/apache-php-mongo          Apache2.4 + PHP + Mongo + m...   2                    [OK] 19hz/mongo-container              Mongodb replicaset for  coreos    1                    [OK] nitra/mongo                       Mongo3 centos7                   1                    [OK] ackee/mongo                       MongoDB with fixed Bluemix p...  1                    [OK] kobotoolbox/mongo                 https://github.com/kobotoolb...  1                    [OK] valtlfelipe/mongo                 Docker Image based on the la...  1                    [OK] 
拉取最新版的 MongoDB 镜像 
这里我们拉取官方的最新版本的镜像:
$ docker pull mongo:latest 
查看本地镜像 
使用以下命令来查看是否已安装了 mongo:
运行容器 
安装完成后,我们可以使用以下命令来运行 mongo 容器:
$ docker run -itd --name mongo -p 27017:27017 mongo --auth 
参数说明:
-p 27017:27017  :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。–auth :需要密码才能访问容器服务。安装成功 
最后我们可以通过 docker ps  命令查看容器的运行信息
接着使用以下命令添加用户和设置密码,并且尝试连接。
$ docker exec  -it mongo mongo admin >  db.createUser({ user:'admin' ,pwd :'123456' ,roles:[ { role:'userAdminAnyDatabase' , db: 'admin' }]}); > db.auth('admin' , '123456' ) 
3 . MongoDB基本使用 3.1 启动MongoDB数据库 3.2 数据库常用命令 show dbs;:查看数据库 > show dbs; admin   0. 000GB config  0. 000GB local   0. 000GB > use youmen	# 切换到指定数据库,如果不存在该数据库就创建。 switched to db youmen > db # 显示当前所在数据库。 youmen > db.dropDatabase() # 删除当前数据库 { "ok"  : 1  } 
3.3 数据集常用命令 db.createCollection(name,options):创建数据集 name:数据集名称 options:可选参数,指定内存大小和索引。 > db.createCollection("student" ); { "ok"  : 1  } show collections;:查看当前数据库中所有集合。 > show collections; student db.student.drop():删除指定数据集 > db.student.drop() true 
3.4 文档常用命令 插入一条文档 
{ 	"acknowledged"  : true , 	"insertedId"  : ObjectId("613ee40f9462ebfb9de4f671" ) } 
插入多条文档 
> db.student.insertMany([ ... {name:"张三" ,age:20 }, ... {name:"李四" ,age:25 } ... ]); { 	"acknowledged"  : true , 	"insertedIds"  : [ 		ObjectId("613ee4349462ebfb9de4f672" ), 		ObjectId("613ee4349462ebfb9de4f673" ) 	] } 
查询所有文档 
> db.student.find(); { "_id"  : ObjectId("613ee40f9462ebfb9de4f671" ), "name"  : "youmen" , "age"  : 18  } { "_id"  : ObjectId("613ee4349462ebfb9de4f672" ), "name"  : "张三" , "age"  : 20  } { "_id"  : ObjectId("613ee4349462ebfb9de4f673" ), "name"  : "李四" , "age"  : 25  } 
查询age>20岁的文档 
> db.student.find( ... {age:{$gt:20 }} ... ) { "_id"  : ObjectId("613ee4349462ebfb9de4f673" ), "name"  : "李四" , "age"  : 25  } 
更新文档 
> db.student.update( ... {name:"youmen" }, ... {name:"wunai" ,age:21 } ... ); WriteResult({ "nMatched"  : 1 , "nUpserted"  : 0 , "nModified"  : 1  }) > db.student.find() { "_id"  : ObjectId("613ee40f9462ebfb9de4f671" ), "name"  : "wunai" , "age"  : 21  } { "_id"  : ObjectId("613ee4349462ebfb9de4f672" ), "name"  : "张三" , "age"  : 20  } { "_id"  : ObjectId("613ee4349462ebfb9de4f673" ), "name"  : "李四" , "age"  : 25  } 
删除文档 
> db.student.deleteOne({name:"李四" }); { "acknowledged"  : true , "deletedCount"  : 1  } > db.student.find() { "_id"  : ObjectId("613ee40f9462ebfb9de4f671" ), "name"  : "wunai" , "age"  : 21  } { "_id"  : ObjectId("613ee4349462ebfb9de4f672" ), "name"  : "张三" , "age"  : 20  } 
命令实在太多,更多命令请参阅官方文档:shell命令 和官方文档:CRUD操作 。
4. Go操作MongoDB 4.1 通过Golang连接MongoDB package  mainimport  (	"context"  	"fmt"  	"log"  	"go.mongodb.org/mongo-driver/mongo"  	"go.mongodb.org/mongo-driver/mongo/options"  ) func  main () 	 	clientOptions := options.Client().ApplyURI("mongodb://1.1.1.1:27017" ) 	 	client, err := mongo.Connect(context.TODO(), clientOptions) 	if  err != nil  { 		log.Fatal(err) 	} 	 	err = client.Ping(context.TODO(), nil ) 	if  err != nil  { 		log.Fatal(err) 	} 	fmt.Println("Connected to MongoDB!" ) } 
如果设置了auth认证,则需要添加认证信息
package  mainimport  (	"context"  	"fmt"  	"go.mongodb.org/mongo-driver/mongo"  	"go.mongodb.org/mongo-driver/mongo/options"  ) func  main () 	var  ( 		err        error 		client     *mongo.Client 		database   *mongo.Database 		collection *mongo.Collection 	) 	 	 	clientOptions := options.Client().ApplyURI("mongodb://127.0.0.1:27017" ) 	client, err = mongo.Connect(context.TODO(), clientOptions) 	if  err != nil  { 		fmt.Println("连接失败!" ) 	} 	 	err = client.Ping(context.TODO(), nil ) 	if  err != nil  { 		fmt.Println("ping 失败" ) 	} 	 	database = client.Database("my_db" ) 	 	collection = database.Collection("my_collection" ) 	fmt.Println(collection.Name()) } 
连接上MongoDB之后,可以通过下面的语句处理我们上面的youmen数据库中的student数据集了:
package  mainimport  (	"context"  	"fmt"  	"go.mongodb.org/mongo-driver/mongo"  	"go.mongodb.org/mongo-driver/mongo/options"  	"log"  ) func  main () 	clientOptions := options.Client().ApplyURI("mongodb://1.1.1.1:27017" ) 	client, err := mongo.Connect(context.TODO(), clientOptions) 	if  err != nil  { 		log.Fatal(err) 	} 	err = client.Ping(context.TODO(), nil ) 	if  err != nil  { 		log.Fatal(err) 	} 	fmt.Println("Connected to MongoDB!" ) 	 	connection := client.Database("youmen" ).Collection("student" ) 	fmt.Println(connection) 	 	err = client.Disconnect(context.TODO()) 	if  err != nil  { 		log.Fatal(err) 	} 	fmt.Println("Connection to MongoDB closed." ) } 
4.2 连接池模式 package  mainimport  (	"context"  	"fmt"  	"go.mongodb.org/mongo-driver/mongo"  	"go.mongodb.org/mongo-driver/mongo/options"  	"log"  	"time"  ) func  ConnectToDB (uri string ,name string ,timeout time.Duration,num uint64 )  (*mongo.Database,error) 	ctx,cancel := context.WithTimeout(context.Background(),timeout) 	defer  cancel() 	o := options.Client().ApplyURI(uri) 	o.SetMaxPoolSize(num) 	client,err := mongo.Connect(ctx,o) 	if  err != nil  { 		return  nil ,err 	} 	return  client.Database(name),nil  } var  num uint64 func  main () 	 	num=20  	clientOptions,err := ConnectToDB("mongodb://1.1.1.1:27017" ,"youmen" , time.Duration(num),20 ) 	fmt.Println(clientOptions) 	if  err != nil  { 		log.Fatal(err) 	} 	err = clientOptions.Client().Ping(context.TODO(), nil ) 	if  err != nil  { 		log.Fatal(err) 	} 	fmt.Println("Connected to MongoDB!" ) 	 	connection := clientOptions.Client().Database("youmen" ).Collection("student" ) 	fmt.Println(connection) 	 	err = clientOptions.Client().Disconnect(context.TODO()) 	if  err != nil  { 		log.Fatal(err) 	} 	fmt.Println("Connection to MongoDB closed." ) } 
5. BSON MongoDB中的JSON文档存储在名为BSON(二进制编码的JSON)的二进制表示中。与其他将JSON数据存储为简单字符串和数字的数据库不同,BSON编码扩展了JSON表示,使其包含额外的类型,如int、long、date、浮点数和decimal128。这使得应用程序更容易可靠地处理、排序和比较数据。
连接MongoDB的Go驱动程序中有两大类型表示BSON数据:D和Raw。
类型D家族被用来简洁地构建使用本地Go类型的BSON对象。这对于构造传递给MongoDB的命令特别有用。D家族包括四类:
D: 一个BSON文档。这种类型应该在顺序重要的情况下使用,比如MongoDB命令。
M: 一张无序的map。它和D是一样的,只是它不保持顺序。
A: 一个BSON数组。
E: D里面的一个元素。
要使用BSON,需要先导入下面包:
import  "go.mongodb.org/mongo-driver/bson" 
下面是一个使用D类型构建的过滤器文档的例子,它可以用来查找name字段与’张三’或’李四’匹配的文档:
bson.D{{ 	"name" , 	bson.D{{ 		"$in" , 		bson.A{"张三" , "李四" }, 	}}, }} 
Raw类型家族用于验证字节切片。你还可以使用Lookup()从原始类型检索单个元素。如果你不想要将BSON反序列化成另一种类型的开销,那么这是非常有用的。这个教程我们将只使用D类型。
5.1 CURD 我们先在Go代码定义一个Student类型如下:
type  Student struct  {	Name string  	Age int  } 
接下来,创建一些Student类型值,准备插入到数据库中:
s1 := Student{"小红" , 12 } s2 := Student{"小兰" , 10 } s3 := Student{"小黄" , 11 } 
插入文档 
使用collection.InsertOne()方法插入一条文档记录:
insertResult, err := collection.InsertOne(context.TODO(), s1) if  err != nil  {	log.Fatal(err) } fmt.Println("Inserted a single document: " , insertResult.InsertedID) 
使用collection.InsertMany()方法插入多条文档记录:
students := []interface {}{s2, s3} insertManyResult, err := collection.InsertMany(context.TODO(), students) if  err != nil  {	log.Fatal(err) } fmt.Println("Inserted multiple documents: " , insertManyResult.InsertedIDs) 
更新文档 
updateone()方法允许你更新单个文档。它需要一个筛选器文档来匹配数据库中的文档,并需要一个更新文档来描述更新操作。你可以使用bson.D类型来构建筛选文档和更新文档:
filter := bson.D{{"name" , "小兰" }} update := bson.D{ 	{"$inc" , bson.D{ 		{"age" , 1 }, 	}}, } 
接下来,就可以通过下面语句找到小兰,给他增加一岁了;
updateResult, err := collection.UpdateOne(context.TODO(), filter, update) if  err != nil  {	log.Fatal(err) } fmt.Printf("Matched %v documents and updated %v documents.\n" , updateResult.MatchedCount, updateResult.ModifiedCount) 
查找文档 
要找到一个文档,你需要一个filter文档,以及一个指向可以将结果解码为其值的指针。要查找单个文档,使用collection.FindOne()。这个方法返回一个可以解码为值的结果。
我们使用上面定义过的那个filter来查找姓名为’小兰’的文档。
var  result Studenterr = collection.FindOne(context.TODO(), filter).Decode(&result) if  err != nil  {	log.Fatal(err) } fmt.Printf("Found a single document: %+v\n" , result) 
要查找多个文档,请使用collection.Find()。此方法返回一个游标。游标提供了一个文档流,你可以通过它一次迭代和解码一个文档。当游标用完之后,应该关闭游标。下面的示例将使用options包设置一个限制以便只返回两个文档。
findOptions := options.Find() findOptions.SetLimit(2 ) var  results []*Studentcur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions) if  err != nil  {	log.Fatal(err) } for  cur.Next(context.TODO()) {	 	var  elem Student 	err := cur.Decode(&elem) 	if  err != nil  { 		log.Fatal(err) 	} 	results = append (results, &elem) } if  err := cur.Err(); err != nil  {	log.Fatal(err) } cur.Close(context.TODO()) fmt.Printf("Found multiple documents (array of pointers): %#v\n" , results) 
删除文档 
最后,可以使用collection.DeleteOne()或collection.DeleteMany()删除文档。如果你传递bson.D{{}}作为过滤器参数,它将匹配数据集中的所有文档。还可以使用collection. drop()删除整个数据集。
deleteResult1, err := collection.DeleteOne(context.TODO(), bson.D{{"name" ,"小黄" }}) if  err != nil  {	log.Fatal(err) } fmt.Printf("Deleted %v documents in the trainers collection\n" , deleteResult1.DeletedCount) deleteResult2, err := collection.DeleteMany(context.TODO(), bson.D{{}}) if  err != nil  {	log.Fatal(err) } fmt.Printf("Deleted %v documents in the trainers collection\n" , deleteResult2.DeletedCount) package  mainimport  (    "fmt"      "reflect"  ) type  person struct  {    name string      age  int  } func  main ()     v := reflect.ValueOf(person{"steve" , 30 })     count := v.NumField()     for  i := 0 ; i < count; i++ {         f := v.Field(i)         switch  f.Kind() {         case  reflect.String:             fmt.Println(f.String())         case  reflect.Int:             fmt.Println(f.Int())         }     } } 
5.2 获取Mongo服务状态 ctx, _ = context.WithTimeout(context.Background(), 30 *time.Second) serverStatus, err := client.Database("admin" ).RunCommand(  ctx,  bsonx.Doc{{"serverStatus" , bsonx.Int32(1 )}}, ).DecodeBytes() if  err != nil  { fmt.Println(err) } fmt.Println(serverStatus) fmt.Println(reflect.TypeOf(serverStatus)) version, err := serverStatus.LookupErr("version" ) fmt.Println(version.StringValue()) if  err != nil  { fmt.Println(err) } 
参考链接Go操作MongoDB - 云+社区 - 腾讯云 (tencent.com) MongoDB 删除数据库 | 菜鸟教程 (runoob.com)