英文:
Storing nested structs with mgo
问题
我正在尝试从一个嵌套非常深的go结构体构建一个mongo文档,但在从go结构体转换为mongo对象的过程中遇到了问题。我在这里构建了一个非常简化的版本来演示:http://play.golang.org/p/yPZW88deOa
运行这段代码会产生以下输出:
&{{2 3} 4}
{"Length":2,"Width":3,"Depth":4}
这完全合理。似乎是Write函数或json.Marshal函数具有某种将嵌套结构体折叠的功能,但当我尝试使用mgo函数func (*Collection) Upsert
将这些数据插入到mongo数据库时,问题就出现了(http://godoc.org/labix.org/v2/mgo#Collection.Upsert)。如果我先使用json.Marshal()
函数并将字节传递给collection.Upsert()
,它会以二进制形式存储,这不是我想要的,但如果我使用collection.Upsert(bson.M("id": id, &c)
,它会以嵌套结构体的形式显示:
{
"Square": {
"Length": 2,
"Width": 3
},
"Depth": 4
}
但我想要的是以与使用os.Stdout.Write()
函数时相同的结构upsert到mongo中:
{
"Length": 2,
"Width": 3,
"Depth": 4
}
是否有一些我忽略的标志可以轻松处理这个问题?我目前唯一能想到的替代方法是通过删除结构体的嵌套来大大降低代码的可读性,但我真的不想这样做。再次强调,我的实际代码比这个示例复杂得多,所以如果我可以通过保持嵌套来避免进一步复杂化代码,那肯定更好。
英文:
I'm trying to build a mongo document from a go struct that is heavily nested, and I'm running into a problem with the transition from go struct to a mongo object. I've built a very simplified version of what I'm trying to work with here: http://play.golang.org/p/yPZW88deOa
package main
import (
"os"
"fmt"
"encoding/json"
)
type Square struct {
Length int
Width int
}
type Cube struct {
Square
Depth int
}
func main() {
c := new(Cube)
c.Length = 2
c.Width = 3
c.Depth = 4
b, err := json.Marshal(c)
if err != nil {
panic(err)
}
fmt.Println(c)
os.Stdout.Write(b)
}
Running this produces the following output:
&{{2 3} 4}
{"Length":2,"Width":3,"Depth":4}
Which makes complete sense. It seems either the Write function or the json.Marshal function has some functionality that collapses the nested struct, but my problem comes when I try to insert this data into a mongo database using the mgo function func (*Collection) Upsert
(http://godoc.org/labix.org/v2/mgo#Collection.Upsert). If I use the json.Marshal()
function first and pass the bytes to collection.Upsert()
, it is stored as binary, which I don't want, but if I use collection.Upsert(bson.M("_id": id, &c)
it appears as a nested struct with the form:
{
"Square": {
"Length": 2
"Width": 3
}
"Depth": 4
}
But what I want to do is upsert to mongo with the same structure as I get when I use the os.Stdout.Write()
function:
{
"Length":2,
"Width":3,
"Depth":4
}
Is there some flag I'm missing that would easily handle this? The only alternative I can see at this point is severely cutting down on the readability of the code by removing the nesting of the structs, which I really hate to do. Again, my actual code is way more complex than this example, so if I can avoid complicating it even more by keeping things nested, that would definitely be preferable.
答案1
得分: 40
我认为对你来说,使用inline
字段标签是最好的选择。mgo/v2/bson文档中指出:
<!-- language: lang-none -->
inline 内联字段,必须是一个结构体或者一个映射,
导致其所有字段或键被处理为外部结构体的一部分。
对于映射,键不能与其他结构体字段的bson键冲突。
然后,你的结构体应该定义如下:
type Cube struct {
Square `bson:",inline"`
Depth int
}
编辑
如果你使用的是mgo/v1/bson
,它也存在inline
字段。
英文:
I think using the inline
field tag is the best option for you. The mgo/v2/bson documentation states:
<!-- language: lang-none -->
inline Inline the field, which must be a struct or a map,
causing all of its fields or keys to be processed as if
they were part of the outer struct. For maps, keys must
not conflict with the bson keys of other struct fields.
Your struct should then be defined as follows:
type Cube struct {
Square `bson:",inline"`
Depth int
}
Edit
inline
also exists in mgo/v1/bson
incase you are using that one.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论