使用 mgo 存储嵌套结构

Posted

技术标签:

【中文标题】使用 mgo 存储嵌套结构【英文标题】:Storing nested structs with mgo 【发布时间】:2014-01-17 22:22:02 【问题描述】:

我正在尝试从高度嵌套的 go 结构构建 mongo 文档,但在从 go 结构到 mongo 对象的转换时遇到了问题。我已经构建了一个 非常 简化版本的我正在尝试使用的内容: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)

运行它会产生以下输出:

&2 3 4
"Length":2,"Width":3,"Depth":4

这完全有道理。似乎 Write 函数或 json.Marshal 函数具有一些折叠嵌套结构的功能,但是当我尝试使用 mgo 函数 func (*Collection) Upsert (http://godoc.org/labix.org/v2/mgo#Collection.Upsert) 将此数据插入 mongo 数据库时,我的问题就出现了。如果我首先使用json.Marshal() 函数并将字节传递给collection.Upsert(),它会以二进制形式存储,这是我不想要的,但如果我使用collection.Upsert(bson.M("_id": id, &c),它会显示为嵌套结构,格式如下:


    "Square": 
        "Length": 2
        "Width": 3
    
    "Depth": 4

但我想做的是使用与我使用 os.Stdout.Write() 函数时相同的结构更新 mongo:


     "Length":2,
     "Width":3,
     "Depth":4

我是否缺少一些可以轻松处理此问题的标志?在这一点上我能看到的唯一选择是通过删除结构的嵌套来严重降低代码的可读性,我真的很讨厌这样做。同样,我的实际代码比这个例子复杂得多,所以如果我可以通过保持嵌套来避免使代码更加复杂,那肯定会更好。

【问题讨论】:

【参考方案1】:

我认为使用inline 字段标签是您的最佳选择。 mgo/v2/bson documentation 声明:

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.

你的结构应该被定义如下:

type Cube struct 
    Square `bson:",inline"`
    Depth  int

编辑

inline 也存在于mgo/v1/bson 中,以防你使用那个。

【讨论】:

谢谢,这正是我知道我忽略的标志类型。 也许文档的措辞可以更好,并提到“嵌入式”字段。

以上是关于使用 mgo 存储嵌套结构的主要内容,如果未能解决你的问题,请参考以下文章

MGO 驱动程序中的更新查询,适用于 bson.M,但不适用于自定义结构

Python字典的嵌套——用于决策树存储树结构

使用 mgo 将数据插入 MongoDB

无法使用带有 golang 的 mgo 检索“_id”值

使用mgo在mongo中删除所有早于使用_id的日期的文档

在 tibble 中的嵌套级别之间移动:如何引用存储在嵌套层次结构的上层中的数据