2012-08-17 8 views
21

In base alla documentazione (http://godoc.org/launchpad.net/mgo/v2) è possibile ottenere l'ID del documento "Upserted" se si utilizza il metodo Upsert.Golang/mgo: Perché mgo non restituisce l'ID del documento inserito?

C'è anche un metodo di inserimento che non fornisce questa funzionalità.
Perché è quello? Cosa succede se voglio eseguire un inserimento anziché un Upsert? (o non sarebbe mai un motivo valido per voler farlo? Sto cominciando a chiedermi.)

risposta

38

Si utilizza bson. NewObjectId() per generare un ID da inserire.

Questo è il modo che ci si inserisce un nuovo documento:

i := bson.NewObjectId() 
c.Insert(bson.M{"_id": i, "foo": "bar"}) 

Dal momento che non si sa se si sta andando per inserire o aggiornare quando si emette un Upsert, sarebbe superfluo per generare un ID solo per rilasciarlo subito dopo la query (nel caso si verifichi un aggiornamento). Questo è il motivo per cui è generato db-side e restituito a te quando applicabile.

+1

Come potrei sostituire "pippo": "bar" con una struct ho già creato? – Acidic

+2

"Se l'applicazione viene riavviata, il generatore Id oggetto inizierà dall'inizio generando sempre gli stessi ID, aggiornando così i record esistenti nel database." questo è pubblicato sulla seconda risposta, è DAVVERO importante e non è menzionato sulla risposta. Penso che dovresti modificare la risposta aggiungendo queste informazioni per le persone in futuro. – cjf93

+0

@ cjf93 Questo non è vero (altro?). Se si esamina l'implementazione di bson.ObjectId, si vedrà che prende in considerazione l'ora corrente. Questo è anche spiegato qui: https://github.com/go-mgo/mgo/issues/392 –

0

Questo non dovrebbe accadere, l'mgo dovrebbe inserire e restituire l'Id, poiché, se abbiamo generato l'ObjectId dall'applicazione stessa, Se l'applicazione viene riavviata, il generatore Id Id inizierà dall'inizio generando lo stesso ID ancora e ancora, quindi aggiornando i record esistenti nel database.

Questo è sbagliato, MGO dovrebbe fare affidamento sul database per generare quegli ID e aggiornare l'oggetto o restituire l'oggetto dell'Id dell'oggetto inserito immediatamente come gli altri linguaggi che si legano a MongoDB come in Python o Java.

+1

Se invece di 'bson.NewObjectId()' si usi 'bson.NewObjectIdWithTime (time.Now())' problema di riavvio dell'applicazione non sarebbe un problema, giusto? –

+0

Sembra piuttosto impossibile leggere il doc ObjectID in quanto il metodo per generare un ObjectID include un timestamp e un PID. Se ti capita di ottenere il PID di esempio e resettare il tuo orologio di sistema, potresti potenzialmente ottenere scontri ObjectID, altrimenti la tua multa. https://docs.mongodb.com/manual/reference/method/ObjectId/ –

0

È sempre possibile provare la funzione Upsert per ottenere l'ID generato.

db := service.ConnectDb() 
sessionCopy := db.Copy() 
defer sessionCopy.Close() // clean up 

collection := sessionCopy.DB(service.MongoDB.DTB).C(MessageCol.tbl) 

log.Println("before to write: ", msg) 

// Update record inserts and creates an ID if wasn't set (Returns created record with new Id) 
info, err := collection.Upsert(nil, msg) 
if err != nil { 
    log.Println("Error write message upsert collection: ", err) 
    return MessageMgo{}, err 
} 

if info.UpsertedId != nil { 
    msg.Id = info.UpsertedId.(bson.ObjectId) 
} 

// gets room from mongo 
room, err := GetRoom(msg.Rid) 
if err != nil { 
    return msg, err 
} 

// increments the msgcount and update it 
room.MsgCount = room.MsgCount + 1 
err = UpdateRoom(room) 
if err != nil { 
    return msg, err 
} 

return msg, err 

Si tratta di un codice di esempio che ho e funziona benissimo .....

Problemi correlati