使用mgo存储嵌套结构体

huangapple go评论82阅读模式
英文:

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:&quot;,inline&quot;`
	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:&quot;,inline&quot;`
	Depth  int
}

Edit

inline also exists in mgo/v1/bson incase you are using that one.

huangapple
  • 本文由 发表于 2013年12月31日 07:58:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/20849591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定