使用Go获取集合中所有键的名称

问题描述

我想获取MongoDB集合中所有键的名称

例如,从此:

 "Id": ObjectId("5f5a010d431c4519dcda0e3d")
            "title": "App"
            "query": ""
            "db": ""
            "widgettype": ""
            "tablename": "active_instance"
            fields:Object
                user:"name",key:"passcode"
            "status": "active"
            "inlibrary": ""
            "createdts": 1599733804

使用“ gopkg.in/mgo.v2”和“ gopkg.in/mgo.v2/bson”软件包

err := mongodbSession.DB(dbname).C(collectionName).Find(bson.M{}).One(&result)
var keyset []string
    for index,_ := range result {
        fmt.Printf("%+v\n",index)
        keyset = append(keyset,index)
    }

    fmt.Println(keyset)

以这种方式获取输出

[_id title query db widgettype  status fields inlibrary createdts ]

未获得作为用户和密钥的子密钥

解决方法

嵌入的文档将在bson.M中显示为另一个result值,因此您必须使用递归来遍历这些值。

这是您可以执行的操作:

func getKeys(m bson.M) (keys []string) {
    for k,v := range m {
        keys = append(keys,k)
        if m2,ok := v.(bson.M); ok {
            keys = append(keys,getKeys(m2)...)
        }
    }
    return
}

使用示例:

m := bson.M{"Id": bson.ObjectId("5f5a010d431c4519dcda0e3d"),"title":      "App","query":      "","db":         "","widgettype": "","tablename":  "active_instance","fields": bson.M{
        "user": "name","key":  "passcode",},"status":    "active","inlibrary": "","createdts": 1599733804,}

keys := getKeys(m)
fmt.Println(keys)

哪个会输出(在Go Playground上尝试):

[db widgettype createdts inlibrary _id title query tablename
  fields user key status]

如果查看结果,将包含userkey,但是无法确定它们是文档的字段还是嵌入式文档的字段。

您可以选择在嵌入文档的字段之前加上嵌入文档字段本身的字段名称,例如。得到fields.userfields.key

这是您可以这样做的方式:

func getKeys(m bson.M) (keys []string) {
    for k,ok := v.(bson.M); ok {
            for _,k2 := range getKeys(m2) {
                keys = append(keys,k+"."+k2)
            }
        }
    }
    return
}

将输出(在Go Playground上尝试输出):

[createdts title query db status inlibrary _id widgettype tablename
    fields fields.user fields.key]

还请注意,上述解决方案不处理数组。如果有数组,则还应该对其进行迭代,并且如果它们包含另一个数组或对象,则应(递归)执行相同的操作。您也可以将它扩展为处理数组。