如何检索[] bson.M类型的地图

时间:2016-02-21 00:43:02

标签: mongodb go struct bson mgo

如何检索多维[] bson.M类型的地图

mongo中的数据就像

"taskData" : { 
    "createdOn" : ISODate("2016-02-20T21:23:11.903Z"), 
    "Task_content" : "@bob", 
    "Priority" : "2", 
    "owner_Uname" : "alice"
}

我尝试访问它的代码

var n []bson.M
 e := collection.Find(bson.M{"users."+strconv.Itoa(j)+".user_name" :   r.FormValue("value[userName]")}).Select(bson.M{"taskData.owner_Uname":1,"_id":0}).All(&n)
if e != nil {
   fmt.Println("Error : ",e)
}else{
   fmt.Println(n[0]["taskData"])
}

获得这样的输出

map[owner_Uname:alice]

我需要使用另一个查询访问此结果字符串。 这是我尝试将其转换为简单地图的界面 newMap :=n[0]["taskData"].(map[string]interface{})但是它给了我一个运行时错误interface conversion: interface {} is bson.M, not map[string]interface {}

result := rawData{}
err := collection.Find(bson.M{"user_name":n[0]["taskData"]["owner_Uname"]}).All(&result)

现在我想在上面的查询中使用它... 请帮助我。提前致谢

编辑: - mongo中的数据就像

{
   "_id" : ObjectId("56bf128f5a9a6a0ebfdd5075"),
     "deadLine" : {
       "Start_time" : ISODate("2016-05-24T00:00:00Z"),
       "End_time" : ISODate("2016-05-29T00:00:00Z")
     },
   },
   "taskData" : { 
       "createdOn" : ISODate("2016-02-20T21:23:11.903Z"), 
       "Task_content" : "@bob", 
       "Priority" : "2", 
       "owner_Uname" : "alice"
   },
   "group" : {
      "1" : {
        "grp_name" : "grp"
       },
      "2" : {
        "grp_name" : "secondGrp"
       }
    }

如果在struct

中使用嵌套struct或map完成,那将对我有用

1 个答案:

答案 0 :(得分:2)

我将为您提供一个帮助您理解的一般示例,因为SO不是一个免费的编码服务,而是一个平台,在这个平台上,同行可以帮助彼此掌握问题。

我的方法是根本不使用 bson.M 作为返回值。

package main

import (
    "fmt"
    "time"

    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
)

type Baz struct {
    Date  time.Time
    Value int
}

type Bar struct {
    Name string
    Baz  []Baz
}

type Foo struct {
    Owner  string
    hidden int
    Bar    Bar
}

const (
    ds   = "localhost:27017"
    db   = "test"
    coll = "nestdemo"
)

func main() {

    o := Foo{
        Owner:  "me",
        hidden: 1,
        Bar: Bar{
            Name: "funky",
            Baz: []Baz{
                Baz{Date: time.Now(), Value: 42},
            },
        },
    }

    // CHECK ERRORS in production environments
    conn, _ := mgo.Dial(ds)
    defer conn.Close()

    c := conn.DB(db).C(coll)
    c.Insert(o)

    l := &Foo{}

    c.Find(bson.M{"owner": "me"}).One(l)

    fmt.Printf("Loaded data: %+v\n", l)
    fmt.Printf(
        "You got your answer to life, the universe and all the rest at %s: %d\n",
        l.Bar.Baz[0].Date.Format(time.Kitchen), l.Bar.Baz[0].Value,
    )
}

您可以在本地计算机上运行此程序(根据需要调整常量),这样可以得到如下输出:

$ go run main.go 
Loaded data: &{Owner:me hidden:0 Bar:{Name:funky Baz:[{Date:2016-02-24 09:00:06.471 +0100 CET Value:42}]}}
You got your answer to life, the universe and all the rest at 9:00AM: 42

相应集合中的条目应如下所示:

{
  "_id" : ObjectId("56cd6306538ba56563bdab76"),
  "owner" : "me",
  "bar" : {
    "name" : "funky",
    "baz" : [
      {
        "date" : ISODate("2016-02-24T08:00:06.471Z"),
        "value" : 42
      }
    ]
  }
}

这里需要注意几点。

  1. 我在结构定义中不需要单个字符来将结构封送到BSON并从BSON封送。它是由mgo according to the rules described in the docs自动完成的。但是,可以自定义(un-)封送的行为,如此处所述。
  2. 未经移植的字段(在此示例中为 hidden )在解组时取零值 - 记住这一点,它可能会让你陷入困境。
  3. 无需使用 bson.M 来处理您的数据,这会让生活变得更轻松 - 例如,无需手动转换类型。
  4. 总结:您需要做的就是创建一个可以将数据解组到的结构。然后你可以像往常一样访问各个字段,没有字符串摆弄等。正如你所看到的那样,这是一点点工作,但是相当简单。

    注意:您显示的数据模型在语法和概念上都是不正确的。暂时搁置前者:将值作为键是一种非常糟糕的做法,如 group 子目录中所示。这将总是迫使你来回处理字符串解析,使你的MongoDB生活变得像开发人员一样复杂。

    我的上述建议假定您将其更正为:

    {
    …
      groups:[
        {grp_id: 1, grp_name: "grp"},
        {grp_id: 2, grp_name: "secondGrp"}
      ]
    …
    }