V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fy1206
V2EX  ›  程序员

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

  •  
  •   fy1206 · 281 天前 · 1297 次点击
    这是一个创建于 281 天前的主题,其中的信息可能已经有所发展或是发生改变。
    12 条回复    2023-07-24 10:01:36 +08:00
    lifespy
        1
    lifespy  
       281 天前 via iPhone
    一时之间我竟不知道如何回答你的问题。难道不能用 orm 吗
    kuaner
        2
    kuaner  
       281 天前
    os.exec()
    jorneyr
        3
    jorneyr  
       281 天前
    这个方案在几个项目里用过了:

    1. 复制一个 MongoDB 客户端程序到 go 程序目录下: 单个文件,50M 左右。
    2. 在 go 程序里使用 exec.Command 执行调用 MongoDB 客户端执行脚本。
    fy1206
        4
    fy1206  
    OP
       281 天前
    @jorneyr 这个方案我有想过。我是看 mysql 的 driver 都有直接执行 sql 文件的方法,想着 mongo-driver 应该也有类似方法,但就是找不到。后来看到有个 RunCommand 的方法可以执行 sql ,但是需要转成 bson.D{}这种格式。
    isexdpac
        5
    isexdpac  
       280 天前
    这种问题还有比 GPT 在行的吗。。
    isexdpac
        6
    isexdpac  
       280 天前
    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
        7
    fy1206  
    OP
       280 天前
    @isexdpac #6 试了 不太行呢 mongo 不支持这个 eval 参数
    isexdpac
        8
    isexdpac  
       280 天前
    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:[email protected]: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
        9
    fy1206  
    OP
       280 天前
    @isexdpac #8 报错 no such command: 'eval'
    fy1206
        10
    fy1206  
    OP
       280 天前
    @isexdpac #8 真的可以运行吗 你 mongo 是啥版本
    isexdpac
        11
    isexdpac  
       278 天前
    @fy1206 mongo 版本 4.0.21
    fy1206
        12
    fy1206  
    OP
       278 天前
    @isexdpac #11 查了下文档, 高版本的 mongo 将 eval 删除了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2767 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 06:36 · PVG 14:36 · LAX 23:36 · JFK 02:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.