2013-08-20 11 views
16

Jestem BARDZO nowy, aby przejść. Z tego, co widziałem na przykładach mGo, w celu wysłania zapytania do kolekcji, a następnie odczytania z niej, należy wstępnie zdefiniować dane, które będą wracać do struktury.Niestrukturalne kolekcje MongoDB z mgo

type Person struct { 
    ID  bson.ObjectId `bson:"_id,omitempty"` 
    Name  string 
    Phone  string 
    Timestamp time.Time 
} 

W PHP dokument został przypisany do tablicy. To było idealne, ponieważ jeden rekord może mieć zupełnie inny zestaw kluczy (może nie zawierać Nazwy lub Telefonu, ale zawiera E-mail) i mógłbym uzyskać do niego bezpośredni dostęp bez ustawiania wstępnie zdefiniowanej klasy/struktury/zmiennej.

Czy jest sposób na to samo w Go/mGo?

Odpowiedz

37

Istnieje wiele sposobów na rozwiązanie tego problemu.

pomocą mapy:

var m bson.M 
err := collection.Find(nil).One(&m) 
check(err) 
for key, value := range m { 
    fmt.Println(key, value) 
} 

Zauważ, że nie ma nic szczególnego bson.M miarę MgO jest zaniepokojony. Jest to po prostu typ map[string]interface{}. Możesz definiować własne typy map i używać ich w mgo, nawet jeśli mają inny typ wartości.

Korzystanie kawałek dokumentu:

bson.D jest kawałek, który jest wewnętrznie znany MgO, i istnieje zarówno zaoferować bardziej skuteczny mechanizm i zaproponować sposób, aby zachować kolejność kluczy, które jest używany przez MongoDB w pewnych okolicznościach (na przykład przy definiowaniu indeksów).

Na przykład:

var d bson.D 
err := collection.Find(nil).One(&d) 
check(err) 
for i, elem := range d { 
    fmt.Println(elem.Name, elem.Value) 
} 

używając, inline mapa pola

,inline bson flag może być również stosowany w dziedzinie map, dzięki czemu można mieć ciastko i je zjeść . Innymi słowy, umożliwia to użycie struktury, dzięki czemu manipulowanie znanymi polami jest wygodne, a jednocześnie umożliwia obsługę nieznanych pól za pomocą wbudowanej mapy.

Na przykład:

type Person struct { 
    ID  bson.ObjectId `bson:"_id,omitempty"` 
    Name  string 
    Phone  string 
    Extra  bson.M `bson:",inline"` 
} 
+0

Cześć Gustavo, dziękuję za szczegółową odpowiedź. Nie wiedziałem o sztuczce "inline" do obsługi opcjonalnych atrybutów. mgo jest naprawdę fantastycznym oprogramowaniem! – tux21b

+0

Czy można to zrobić na Find (zero). All (& m)? –

2

Można przechowywać wszystko na mapie. Pakiet mgo/bson zapewnia typ danych bson.M, który może być używany do przechowywania dowolnych danych, a ponieważ MongoDB nie wymusza silnego schematu, mgo wewnętrznie używa typu bson.M we wszystkim.

Jeśli chcesz tylko wyświetlić dane, użycie bson.M powinno być w porządku, ale gdy chcesz zacząć pracę z tym, powinieneś rozważyć użycie struct. W przeciwnym razie potrzebowałbyś wielu typów asercji w swoim programie. Załóżmy na przykład, że chcesz wydrukować tytuł (result["title"]) swojego dokumentu wielkimi literami. Używając tylko bson.M, Twój kod będzie wyglądać następująco:

// is there a title attribute? 
if title, ok := result["title"]; ok { 
    // is it a string? (and not another map or integer or something else) 
    if titleStr, ok := title.(string); ok { 
     // ok, it is a string 
     fmt.Println("Title: ", strings.ToUpper(titleStr)) 
    } 
} 

Program stanie się znacznie bardziej czytelne i łatwiejsze do utrzymania, gdy pozwalasz mgo konwersji danych do struct dla Ciebie. Następnie ten sam kod może odczytać jako:

fmt.Println(strings.ToUpper(result.Title)) 

Zwykle definiuje jeden typ struct dla każdego typu dokumentu, który ma do czynienia z (czyli jednego typu dla „użytkowników”, inny dla „blogach”, etc.), który zawiera każdy atrybut, do którego możesz chcieć uzyskać dostęp. Jeśli twój dokument użytkownika nie ma przypisanego adresu e-mail, po dekodowaniu otrzymasz pusty ciąg (lub bardziej ogólnie wartość zerową).

+0

Dzięki reagowania. Podałem także nieco bardziej szczegółową odpowiedź. Należy pamiętać, że w dostępie do map brakuje asercji typów. –

+0

Dziękuję, dodałem brakującą asercję typu. – tux21b

+0

Nie ma za co. Na potrzeby zapisu, ten konkretny przypadek mógł zostać obsłużony w pojedynczym ujęciu, z 'wynikiem [" title "]. (String)', ale twój kod i objaśnienie jest bardziej pouczające. –