2013-08-20 17 views
16

Sono MOLTO nuovo da fare. Da quello che ho visto negli esempi di mGo, per poter interrogare una raccolta e poi leggerla da essa, è necessario predefinire i dati che torneranno in una struttura.Collezioni MongoDB non strutturate con mgo

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

In PHP, il documento è stato assegnato a un array. Questo era perfetto in quanto un record può avere un set di chiavi completamente diverso (potrebbe non contenere Nome o Telefono ma contenere Email) e potrei accedervi direttamente senza impostare una classe/struct/variabile predefinita.

C'è un modo per fare lo stesso in Go/mGo?

risposta

37

Ci sono molti modi per gestirlo.

Utilizzando una mappa:

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

Nota che non c'è niente di speciale bson.M quanto MgO è interessato. È solo un tipo map[string]interface{} e puoi definire i tuoi tipi di mappe e usarli con mgo, anche se hanno un tipo di valore diverso.

Utilizzando una fetta documento:

Il bson.D è una fetta che è noto internamente MgO, ed esiste sia per offrire un meccanismo più efficiente e offrire un modo per preservare l'ordinamento delle chiavi, che è usato da MongoDB in alcune circostanze (ad esempio, quando si definiscono gli indici).

Ad esempio:

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

L'utilizzo di un, in linea mappa del campo

Il ,inline BSON flag può essere utilizzato anche in un campo mappa, in modo che si può avere la botte piena e la moglie ubriaca . In altre parole, abilita l'uso di una struct in modo che la manipolazione di campi noti sia conveniente e allo stesso tempo consenta di gestire campi sconosciuti tramite la mappa in linea.

Ad esempio:

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

Ciao Gustavo, grazie per la tua risposta dettagliata. Non ho saputo del trucco "in linea" per gestire gli attributi opzionali. mgo è davvero un fantastico software! – tux21b

+0

È possibile eseguire su Trova (nil). Tutti (& m)? –

2

È possibile memorizzare tutto in una mappa. Il pacchetto mgo/bson fornisce un tipo di dati bson.M che può essere utilizzato per archiviare dati arbitrari e poiché MongoDB non applica uno schema potente, mgo utilizza internamente il tipo bson.M per tutto.

Se si desidera solo visualizzare i dati, utilizzare un bson.M dovrebbe andare bene, ma una volta che si desidera iniziare a lavorare con esso, si dovrebbe prendere in considerazione l'utilizzo di una struttura invece. Altrimenti, avresti bisogno di molte affermazioni di tipo nel tuo programma. Ad esempio, si consideri che si desidera stampare il titolo (result["title"]) del documento in maiuscolo. Utilizzando solo bson.M, il codice sarà simile:

// 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)) 
    } 
} 

Il vostro programma sarebbe diventato molto più leggibile e più facile da mantenere quando si lascia mgo convertire i dati in una struct per voi. Poi, lo stesso codice potrebbe leggere come:

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

Normalmente si definisce un tipo struct per ogni tipo di documento che si vuole affrontare (per esempio un tipo di "utenti", un altro per "post del blog", ecc) che contiene tutti gli attributi a cui potresti voler accedere. Se al tuo documento utente non viene assegnato un indirizzo e-mail, ti verrà restituita una stringa vuota (o più in generale, il valore zero) quando la decodifichi.

+0

Grazie per rispondere. Ho fornito anche una risposta leggermente più dettagliata. Si noti che c'è un asserzione di tipo mancante nell'accesso alla mappa. –

+0

Grazie, ho aggiunto l'asserzione di tipo mancante. – tux21b

+0

Prego. Per la cronaca, questo caso specifico avrebbe potuto essere gestito in un colpo singolo, con 'result [" title "]. (Stringa)', ma il tuo codice e la spiegazione sono più istruttivi. –

Problemi correlati