Хранение вложенных структур с помощью mgo

Я пытаюсь построить документ mongo из структуры go, которая сильно вложенна, и я столкнулся с проблемой перехода от go struct к объекту 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 имеет некоторую функциональность, которая сворачивает вложенную структуру, но моя проблема возникает, когда я пытаюсь вставить эти данные в базу данных mongo, используя функцию mgo func (*Collection) Upsert (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
}

Но то, что я хочу сделать, это upsert to mongo с той же структурой, что и я, когда я использую функцию os.Stdout.Write():

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

Есть ли какой-то флаг, который мне не хватает, что бы легко справиться с этим? Единственная альтернатива, которую я вижу на этом этапе, - это серьезно сократить читаемость кода, удалив вложенность структур, что я действительно ненавижу делать. Опять же, мой фактический код является более сложным, чем этот пример, поэтому, если я могу избежать еще большего усложнения, удерживая вещи вложенными, это определенно было бы предпочтительным.

Ответ 1

Я думаю, что использование тега поля inline - лучший вариант для вас. В документации mgo/v2/bson указано:

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
}

Edit

inline также существует в mgo/v1/bson, если вы используете его.