英文:
How to retrieve []bson.M type of map
问题
如何检索多维[]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"
}
}
如果使用嵌套结构或结构中的映射,这对我也有用。
英文:
How to retrieve multidimensional []bson.M type of map
The data in mongo is like
"taskData" : {
"createdOn" : ISODate("2016-02-20T21:23:11.903Z"),
"Task_content" : "@bob",
"Priority" : "2",
"owner_Uname" : "alice"
}
The code through which i tried to access it
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"])
}
getting output like this
map[owner_Uname:alice]
I need to access this resultant string with another query.
It is a interface i tried to convert it to simple map
newMap :=n[0]["taskData"].(map[string]interface{})
but it gives me an runtime error 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)
Now I want to use it in above query ...
Kindly help me out. Thanks in advance
Edit :-
The data in mongo is like
{
"_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"
}
}
That will work me too if it is done with nested struct or map in struct
答案1
得分: 5
我将为您提供一个通用示例,以帮助您理解,因为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
}
]
}
}
这里有几点需要注意:
- 我的结构定义中没有一个字符是为了将结构体编组为BSON而存在的。这是由mgo自动完成的,根据文档中描述的规则。但是,您可以根据需要自定义(反)编组的行为,如文档中所述。
- 未导出的字段(在此示例中为**
hidden
**)在解组时会采用其零值-请记住这一点,它可能会给您带来麻烦。 - 没有必要使用**
bson.M
**来处理数据,这样会使生活变得更加轻松-例如,无需手动进行类型转换。
总结:您只需要创建一个可以将数据解组到的结构体。然后,您可以像往常一样访问各个字段,而无需进行字符串操作等。这是一项工作,但是相当简单,正如您所看到的。
注意:您展示的数据模型在语法和概念上都是不正确的。暂时不考虑前者:将值作为键是一种非常糟糕的做法,如**group
**子文档中所示。这将始终迫使您在字符串解析之间来回处理,使您作为开发人员在使用MongoDB时变得非常复杂。
我上面的建议假设您将其更正为类似以下内容的内容:
{
…
groups:[
{grp_id: 1, grp_name: "grp"},
{grp_id: 2, grp_name: "secondGrp"}
]
…
}
英文:
I'll provide you with a general example to help you understand, since SO is not a free coding service, but a platform where peers help each other to take a grasp on the problem.
My approach is not to use bson.M
at all for the returned value.
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,
)
}
You can run this program on you local machine (with the constants adjusted as needed), which should give you an output looking like this:
$ 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
The entry in the according collection should read something like this:
{
"_id" : ObjectId("56cd6306538ba56563bdab76"),
"owner" : "me",
"bar" : {
"name" : "funky",
"baz" : [
{
"date" : ISODate("2016-02-24T08:00:06.471Z"),
"value" : 42
}
]
}
}
A few things are to note here.
- I didn't need a single character in my struct definitions to have the structs marshaled to and marshaled from BSON. It was done automagically by mgo according to the rules described in the docs. However, you can customize the behavior of the (un-)marshaling, as described there.
- Unexported fields (
hidden
in this example) take their zero value upon unmarshalling – keep that in mind, it can bite you in the neck. - There is no need to use
bson.M
to handle your data, which makes life a lot easier – no manual type conversions, for example.
In summary: All you need to do is to create a struct your data can be unmarhaled into. Then you can access the various fields as usual, without string fiddling and alike. That's bit of work, but a rather trivial one, as you can see.
Note: The data model you have shown is both syntactically and conceptually incorrect. Setting aside the former for now: It is a very bad practice to have values as keys, as shown in the group
subdoc. This will always force you to deal with string parsing back and forth, making your life with MongoDB as complicated as it can get as a developer.
My above suggestion assumes you will correct that into something like:
{
…
groups:[
{grp_id: 1, grp_name: "grp"},
{grp_id: 2, grp_name: "secondGrp"}
]
…
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论