2012-08-17 11 views
21

ドキュメント(http://godoc.org/launchpad.net/mgo/v2)によれば、Upsertメソッドを使用すると、 "Upserted"ドキュメントのIDを取得できます。Golang/mgo:なぜmgoは挿入された文書のIDを返さないのですか?

この機能を提供しないInsertメソッドもあります。
なぜですか?アップアップの代わりにインサートを実行する場合はどうすればよいですか? (または、これまで私は疑問に思い始めている?それをやりたいために何らかの正当な理由ではありません。)

答えて

38

あなたはbsonを使用しています。 NewObjectId()を使用して挿入するIDを生成します。あなたは、あなたがUpsertを発行したときに挿入または更新しようとしているかどうかを知りませんので、

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

生成する余分のようになります。

この

は、新しい文書を挿入したい方法ですIDは、クエリの直後にドロップするだけです(更新が発生した場合)。そのため、db-sideが生成され、適用可能な場合に返されます。

+1

は、どのように私は「foo」を置き換えることができますか? – Acidic

+2

"アプリケーションが再起動した場合、オブジェクトIDジェネレータは最初から同じIDを繰り返し生成し、データベース内の既存のレコードを更新します。これは2番目の回答に掲載されており、本当に重要であり、答えに言及されていません。私はあなたが将来この情報を人に追加する答えを編集すべきだと思います。 – cjf93

+0

@ cjf93これは当てはまりません。 bson.ObjectIdの実装を見ると、現在の時刻が考慮されます。これはここでも説明しています:https://github.com/go-mgo/mgo/issues/392 –

0

これはまったく起こってはいけません。アプリケーション自体からObjectIdを生成した場合、アプリケーションが再起動すると、オブジェクトIDジェネレータは最初から同じものを生成するため、Idを挿入して返します。 IDを何度も繰り返して、データベース内の既存のレコードを更新します。

これは間違っています。MGOは、MongoDBにバインドしている他の言語がPythonやJavaで好きなように、これらのIDを生成したり、オブジェクトを更新したり、挿入されたオブジェクトのobjectIdを返すのにデータベースを利用する必要があります。

+1

'bson.NewObjectId()の代わりに' bson.NewObjectIdWithTime(time.Now()) 'を使うと、アプリケーションの再起動の問題は問題ではないでしょうか? –

+0

ObjectIDを生成するメソッドには、タイムスタンプとPIDが含まれているため、これはObjectIDドキュメントを読むのが難しいと思われます。サンプルPIDを取得してシステムクロックをリセットした場合、ObjectIDの衝突が発生する可能性があります。 https://docs.mongodb.com/manual/reference/method/ObjectId/ –

0

Upsert関数を使用して、生成されたIDを取得できます。私はすでに作成している構造体と「バー」:

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 

これは私が持っているサンプルコードであり、正常に動作します.....

関連する問題