当前位置: 首页 > 工具软件 > go-adodb > 使用案例 >

Go语言连接MongoDB和SQLServer(附MongoDB修改查询)

谯嘉胜
2023-12-01

前言

之前客户有一个需求,需要用Go语言将一个服务器的MongoDB数据,定期同步到另一个服务器的SQL Server数据库中,由于两个数据库都采用了含有特殊字符的密码,因此踩了不少坑,特此来记录一下。

一、MongoDB的连接、查询和修改

1、无账户和密码的连接

以mongo-driver连接MongoDB为例,使用前需要导入相关包,为了让大家看得直观一点,以下代码均采用硬编码方式将连接参数直接写出来
连接数据库的URI格式:“mongodb://{服务器IP地址}:{数据库端口号}”

import (
    //此处省略其他包......
    "context"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)
func connectDatabase() {
	var err error
	var Option *options.ClientOptions
    var Client *mongo.Client
    var uri string
    //URI格式:"mongodb://{服务器IP地址}:{数据库端口号}"
    uri = "mongodb://127.0.0.1:27017"
	Option = options.Client().ApplyURI(uri)
	Client, err = mongo.Connect(Context, Option)
	if err != nil {
		log.Fatal(err)
	}
	err = Client.Ping(Context, nil)
	if err != nil {
		log.Fatal(err)
	}
	//Database()参数填你要连接的数据库名,此处为“test”
	MongoDb = Client.Database("test")
}

2、有账户和密码(无特殊字符)的连接

带账户密码,且账户密码包含特殊字符(比如“+&=<>"#,%{}|^~[]`;/?:@$”),只需要修改一下URI格式。
连接数据库的URI格式:
“mongodb://{数据库用户名}:{数据库密码}@{服务器IP地址}:{数据库端口号}”

    //URI格式:"mongodb://{数据库用户名}:{数据库密码}@{服务器IP地址}:{数据库端口号}"
    //如:"mongodb://root:1234@127.0.0.1:27017"
    //此处账户是root,密码是1234
    uri = "mongodb://root:1234@127.0.0.1:27017"
    Option = options.Client().ApplyURI(uri)

3、账户和密码带特殊字符的连接

解决步骤:
1.先使用net/url包的QueryEscape()方法对特殊字符进行转义,构造正确的URI,作为参数传入ApplyURI()方法
2.构造Credential,写入数据库名、账号和密码,再使用SetAuth()方法,将Credential传进去

PS:个人猜测,由于有了Credential,里面已经写入了数据库名、账号和密码,向ApplyURI()方法传入的URI应该就不需要再加账户和密码了,只需要服务器IP和数据库端口号就行了,所以步骤1可能是多余的,大家可以自己去试一下,我这里就偷个懒不测了~

import (
    //此处省略其他包......
	"net/url"
)
// 对URI中数据库账号和密码中的特殊字符进行转义
func escapeCharacter(str string) string {
    //省略部分代码......
	if strings.ContainsAny(str, "+&=<>\"#,%{}|\\^~[]`;/?:@$") {
		escapedUrlStr := url.QueryEscape(str)
		return escapedUrlStr
	}
	//省略部分代码......
}
func connectDatabase() {
    //省略部分代码......
    //此处账户是@root,密码是@1234@,用户名和密码有特殊字符,需要转义
    uri = "mongodb://" + escapeCharacter("@root") + ":" + escapeCharacter("@1234@") + "@127.0.0.1:27017"
    var credential options.Credential
	credential = options.Credential{
		AuthSource: "test",
		Username:   "@root",
		Password:   "@1234@",
	}
	Option = options.Client().ApplyURI(uri).SetAuth(credential)
	Client, err = mongo.Connect(Context, Option)
    //省略部分代码......
}

4、带条件查询:

前面已经获取了对MongoDB指定数据库的连接(通过Client.Database()方法会返回一个database的指针)现在要查询,只需要指定查询的表和查询条件即可。

首先使用bson对象构造查询条件,然后调用find()方法实现带条件查询,find()方法会返回一个游标,最后再循环调用find.Next()方法,不断访问游标查询到的文档(可以理解为关系型数据库的记录),并使用find.Decode()方法对获取的文档进行解码,然后根据你的需要进行下一步处理

操作之前需要导入bson包:“go.mongodb.org/mongo-driver/bson”

import (
    //此处省略其他包......
	"go.mongodb.org/mongo-driver/bson"
)
func (dlist *DataList) Query() {
    //省略部分代码......
	dlist.List = []Data{}
	//选择要查询的表(集合)
	var coll *mongo.Collection
	coll = MongoDb.Collection("sys_user")
	filter := bson.M{"status": "0"}
	// 返回的是一个游标
	find, err := coll.Find(context.TODO(), filter)
	if err != nil {
		log.Fatal("在XX表中查询数据出错", err)
		return
	}
	// 查询完要关闭游标
	defer find.Close(context.TODO())
	// 不断访问游标获取查询到的文档
	for find.Next(context.TODO()) {
		row := Data{}
		var getline interface{}
		err = find.Decode(&getline)
		if err != nil {
			log.Fatal("解码XX表中的数据出错", err)
		}
		myline := []KeyVal{}
		sByte, _ := json.Marshal(getline)
		_ = json.Unmarshal(sByte, &myline)
		//使用自定义方法GetMap()格式化数据
		row.GetMap(myline)
		dlist.List = append(dlist.List, row)
	}
	//省略部分代码......
}

5、修改:

修改和查询类似,首先使用bson对象构造修改的字段和修改的值,然后调用UpdateOne()或UpdateMany()方法(这俩方法分别对应修改单个文档和修改多个文档)执行修改操作

for index, item := range dataList {
		//省略部分代码......
		//在MongoDB中更新转移状态
		c := MongoDb.Collection("sys_user")
		//新的数据
		updateData := bson.D{{"$set", bson.D{{"status", "1"}}}}
		_, err = c.UpdateMany(Context, bson.D{{"id", item.Id}}, updateData)
		if err != nil {
			log.Fatal("更新XX表中第"+strconv.Itoa(index)+"条记录出错", err)
		}
		//省略部分代码......
	}

二、SQL Server的连接

1、有账户和密码(无特殊字符)且使用默认实例的连接

import (
    //此处省略其他包......
    "database/sql"
    _ "github.com/mattn/go-adodb"
)
    //省略部分代码......
    var SqlServerDb *sql.DB
    var conf []string
	conf = append(conf, "Provider=SQLOLEDB")
    conf = append(conf, "Data Source=127.0.0.1,1433") // IP,端口号
	conf = append(conf, "Initial Catalog=test")       // 数据库名
	conf = append(conf, "user id=sa")                 // 用户名
	conf = append(conf, "password=root")              // 密码
	fmt.Println(strings.Join(conf, ";"))
	SqlServerDb, err = sql.Open("adodb", strings.Join(conf, ";"))
	if err != nil {
		log.Fatal(err)
		fmt.Println("访问SQL Server数据库失败", err)
		return
	}
	//省略部分代码......

2、有账户和密码(含特殊字符)且不使用默认实例的连接

    //省略部分代码......
    conf = append(conf, "Provider=SQLOLEDB")
    // sqlserver IP,端口号\实例名
    conf = append(conf, "Data Source=127.0.0.1,1433\\admin")
	conf = append(conf, "Initial Catalog=test")       // 数据库名
	conf = append(conf, "user id=@sa")                 // 用户名
	conf = append(conf, "password=@root@")              // 密码
	fmt.Println(strings.Join(conf, ";"))
	SqlServerDb, err = sql.Open("adodb", strings.Join(conf, ";"))
	//省略部分代码......

SQL Server这类关系型数据库的增删改查比较常用,网上资料也比较多,本文就不赘述啦,这篇文章主要用于自己总结回顾,如果能给大家带来帮助自然是再好不过啦!

 类似资料: