用 go 怎么执行 mongo 的脚本文件

292 天前
 fy1206
1312 次点击
所在节点    程序员
12 条回复
lifespy
292 天前
一时之间我竟不知道如何回答你的问题。难道不能用 orm 吗
kuaner
292 天前
os.exec()
jorneyr
292 天前
这个方案在几个项目里用过了:

1. 复制一个 MongoDB 客户端程序到 go 程序目录下: 单个文件,50M 左右。
2. 在 go 程序里使用 exec.Command 执行调用 MongoDB 客户端执行脚本。
fy1206
292 天前
@jorneyr 这个方案我有想过。我是看 mysql 的 driver 都有直接执行 sql 文件的方法,想着 mongo-driver 应该也有类似方法,但就是找不到。后来看到有个 RunCommand 的方法可以执行 sql ,但是需要转成 bson.D{}这种格式。
isexdpac
292 天前
这种问题还有比 GPT 在行的吗。。
isexdpac
292 天前
package main

import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"io/ioutil"
)

func main() {
// 建立 MongoDB 会话,连接到数据库(同步代码)

session, err := mgo.Dial("mongodb://localhost:27017")
if err != nil {
panic(err)
}
defer session.Close()

session.SetMode(mgo.Monotonic, true)
db := session.DB("your_database_name")

// 读取脚本文件内容
script, err := ioutil.ReadFile("your_script_file.js")
if err != nil {
panic(err)
}

// 执行脚本文件
result := bson.M{}
err = db.Run(bson.M{"eval": string(script)}, &result)
if err != nil {
panic(err)
}

// 处理脚本执行结果
// ...
}
在上面的代码中,我们首先建立了一个 MongoDB 会话并连接到数据库。然后,我们使用 ioutil 包读取脚本文件的内容,并使用 db.Run 方法执行脚本文件。db.Run 方法的第一个参数是一个包含脚本的 bson.M 类型的 map ,键为"eval",值为脚本内容的字符串。第二个参数是用于接收脚本执行结果的变量。脚本执行结果通常是一个包含查询结果的 map 。

请注意替换上面代码中的 your_database_name 为你要连接的 MongoDB 数据库的名称,并将 your_script_file.js 替换为你要执行的脚本文件路径。
fy1206
292 天前
@isexdpac #6 试了 不太行呢 mongo 不支持这个 eval 参数
isexdpac
292 天前
script.txt 脚本文件:
db.file.insertOne({"name":"test1","age":10})
db.file.insertOne({"name":"test2","age":11})
db.file.insertOne({"name":"test3","age":12})
db.file.find({name:"test2"})

代码:
package http

import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"os"
"strings"
"testing"
"time"
)

func TestRunMongoFile(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
clientOptions := options.Client().ApplyURI("mongodb://admin:123456@x.x.x.x:27017")
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
t.Fatal(err)
}
err = client.Ping(ctx, nil)
if err != nil {
t.Fatal(err)
}
database := client.Database("test")
fileContent, err := os.ReadFile("./script.txt")
if err != nil {
t.Fatal(err)
}
commands := strings.Split(string(fileContent), "\n")
for _, cmd := range commands {
if len(cmd) == 0 {
continue
}
var result bson.M
err = database.RunCommand(ctx, bson.D{{"eval", cmd}}).Decode(&result)
if err != nil {
t.Fatal(err)
}
fmt.Println(result)
}
}
我测试了下没啥问题,不知道是不是你要的效果,不过如果文件里执行 sql 多的话,context.WithTimeout 时间要改大一点
fy1206
292 天前
@isexdpac #8 报错 no such command: 'eval'
fy1206
292 天前
@isexdpac #8 真的可以运行吗 你 mongo 是啥版本
isexdpac
289 天前
@fy1206 mongo 版本 4.0.21
fy1206
289 天前
@isexdpac #11 查了下文档, 高版本的 mongo 将 eval 删除了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/958549

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX