为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕无忌1623718 2022-09-26 19:36:23
我在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 dynamicfor cursor.Next(context.Background()) {    err := cursor.Decode(&obj)    if err != nil {        log.Fatal(err)    }    log.Printf("%#v\n", obj)}有没有办法做到这一点,而不会重复很多次?我意识到动态类型语言会更好。想在将工作迁移到脚本语言之前询问。我尝试过使用反射包和 switch 语句来动态实例化变量,并使用接口{} 类型,但这迫使解码使用 bson 类型而不是我定义的结构。
查看完整描述

1 回答

?
富国沪深

TA贡献1790条经验 获得超9个赞

有很多方法可以做到这一点。其中之一是使用回调函数:


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)


这样,您可以将迭代放入公共函数中,并使用闭包来处理特定于类型的逻辑。


查看完整回答
反对 回复 2022-09-26
  • 1 回答
  • 0 关注
  • 114 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信