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

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

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

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

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


person Verran    schedule 30.12.2013    source источник


Ответы (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
}

Изменить

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

person ANisus    schedule 31.12.2013
comment
Спасибо, это был именно тот тип флага, который я знал, что не замечал. - person Verran; 31.12.2013
comment
Возможно, документацию можно было бы сформулировать лучше и упомянуть встроенные поля. - person Ostati; 15.02.2017