猿问

在 mongodb 中循环访问集合并解码为各种 go 结构

我在mongodb实例中有一系列集合,我想拉取所有集合并解码集合中的所有文档,以便我可以随时更改它们。


我使用go来列出集合名称:


...

collections, err := db.ListCollectionNames(context.TODO(), bson.M{})

if err != nil {

    log.Fatalf("Failed to get coll names: %v", err)

}


for _, coll := range collections {

    collection := db.Collection(coll)

...

这完美地工作,下一步是打开每个集合的游标,并在光标上循环,并将每个对象的解码调用为其相应的类型。


我已经定义了类型包中的所有类型:


type Announcements struct {

    Id            string    `bson:"_id"`

    Content       string    `bson:"content"`

    Title         string    `bson:"title"`

    DateModified  time.Time `bson:"dateModified,omitempty"`

    ModifiedBy    string    `bson:"modifiedBy,omitempty"`

}

问题是我无法定义用于动态解码的变量。


需要为每个集合重复此代码


var obj Announcements // This would need to be dynamic


for cursor.Next(context.Background()) {

    err := cursor.Decode(&obj)

    if err != nil {

        log.Fatal(err)

    }


    log.Printf("%#v\n", obj)

}

有没有办法做到这一点,而不会重复很多次?我意识到动态类型语言会更好。想在将工作迁移到脚本语言之前询问。


我尝试过使用反射包和 switch 语句来动态实例化变量,并使用接口{} 类型,但这迫使解码使用 bson 类型而不是我定义的结构。


慕无忌1623718
浏览 115回答 1
1回答

富国沪深

有很多方法可以做到这一点。其中之一是使用回调函数:func Process(cursor *mongo.Cursor, cb func(), out interface{}) {  for cursor.Next(context.Background()) {     err := cursor.Decode(out)     if err != nil {         log.Fatal(err)     }     cb()     log.Printf("%#v\n", obj)  }}然后定义一个映射:type collHandler struct {   New func() interface{}   Process func(interface{})}var collections=map[string]func() interface{} {   "announcements":   collHandler{     New: func() interface {} {return &Announcement{}},     Process: func(data interface{}) {        processAnnouncements(data.(*Announcement))     },   },   ...}然后,您可以:handler:=collections[collectionName]obj:=handler.New()process(cursor,func() {   handler.Process(obj)  },  &obj)这样,您可以将迭代放入公共函数中,并使用闭包来处理特定于类型的逻辑。
随时随地看视频慕课网APP

相关分类

Go
我要回答