2012-08-17 7 views
21

Zgodnie z dokumentacją (http://godoc.org/launchpad.net/mgo/v2) można uzyskać identyfikator dokumentu "Upserted", jeśli użyto metody Upsert.Golang/mgo: Dlaczego mgo nie zwraca identyfikatora wstawionego dokumentu?

Istnieje również metoda Insert, która nie zapewnia tej funkcji.
Dlaczego tak jest? Co zrobić, jeśli chcę wykonać Insert zamiast Upsert? (lub nigdy nie byłby żaden ważny powód, aby chcieć to zrobić? Zaczynam się zastanawiać.)

Odpowiedz

38

Używasz bson. NewObjectId(), aby wygenerować identyfikator do wstawienia.

To jak chcesz wstawić nowy dokument:

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

Ponieważ nie wiem, czy masz zamiar wstawić lub aktualizacji podczas wystawienia Upsert byłoby zbędne do wygenerowania ID, aby upuścić go zaraz po zapytaniu (na wypadek, gdyby aktualizacja się wydarzyła). Dlatego jest generowana strona db-side i zwracana w razie potrzeby.

+1

Jak mógłbym zastąpić "foo": "bar" z struct już stworzył? – Acidic

+2

"Jeśli aplikacja zostanie zrestartowana, generator Object Ideli rozpocznie od początku generowanie tych samych identyfikatorów, co spowoduje aktualizację istniejących rekordów w bazie danych." to jest zamieszczone na drugiej odpowiedzi, jest NAPRAWDĘ ważne i nie jest wymienione w odpowiedzi. Myślę, że powinieneś edytować odpowiedź dodającą te informacje dla osób w przyszłości. – cjf93

+0

@ cjf93 To nie jest prawda (więcej?). Jeśli spojrzysz na implementację bson.ObjectId, zobaczysz, że bierze pod uwagę obecny czas. Zostało to również wyjaśnione tutaj: https://github.com/go-mgo/mgo/issues/392 –

0

To nie powinno się w ogóle dziać, mgo powinno wstawić i zwrócić ID, ponieważ jeśli wygenerujemy ObjectId z samej aplikacji, Jeśli aplikacja zostanie zrestartowana, generator Id Object zacznie od początku generować ten sam Identyfikatory raz po raz, a tym samym aktualizowanie istniejących rekordów w bazie danych.

To źle, MGO powinien polegać na bazie danych podczas generowania tych identyfikatorów i aktualizacji obiektu lub zwracania ID obiektu wstawionego obiektu, tak jak to, jakie inne języki wiążą się z MongoDB w języku Python lub Java.

+1

Jeśli zamiast 'bson.NewObjectId()' użyłoby 'bson.NewObjectIdWithTime (time.Now())' problem ponownego uruchomienia aplikacji nie byłby problemem, prawda? –

+0

To wydaje się raczej niemożliwe czytanie dokumentu ObjectID, ponieważ metoda generowania identyfikatora obiektu zawiera znacznik czasu i PID. Jeśli zdarzy ci się uzyskać przykładowy PID i zresetować zegar systemowy, potencjalnie dojdzie do kolizji ObjectID, w przeciwnym razie grzywna. https://docs.mongodb.com/manual/reference/method/ObjectId/ –

0

Zawsze można wypróbować funkcję Upsert, aby uzyskać wygenerowany identyfikator.

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 

To jest przykładowy kod mam i działa dobrze .....

Powiązane problemy