摘要:實際情況默認情況下,使用自動生成,而且在自帶的命令里,無法指定一個自增字段。自增字段在多線程時必須是原子性的,這在大數據情況下很難實現伸縮性。而且,在里面,有一個命令是原子性的。代碼如下無法打開創建個模擬多線程環境輸出查詢結果
實際情況
默認情況下,mongo使用_id自動生成uniq id,而且在mongo自帶的命令里,無法指定一個自增字段。自增字段在多線程時必須是原子性的,這在大數據情況下很難實現伸縮性(scalability)。
Generally in MongoDB, you would not use an auto-increment pattern for
the _id field, or any field, because it does not scale for databases
with large numbers of documents. Typically the default value ObjectId
is more ideal for the _id.
不過好消息是,_id不一定非得是ObjectId類型,它可以是任何類型。而且,在mongo里面,有一個findAndModify命令是原子性的。我們可以使用它實現auto increment ID。
在golang的mgo庫里,Apply命令可以實現findAndModify功能
假設我們要把test表的_id字段設置為自增的,我們需要先創建一個counter表,這個表里面保存一個seq字段,通過在seq上使用Apply,獲取新doc的seq值作為test表中下一個id的值。
代碼如下:package main import ( "fmt" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" "log" "math/rand" "sync" ) func init() { log.SetFlags(log.Lshortfile | log.LstdFlags) } func main() { session, err := mgo.Dial("usr:pwd@127.0.0.1:27017/dbname") if err != nil { log.Fatal("無法打開MongoDB!") return } defer session.Close() clt := session.DB("dbname").C("test") getNextSeq := func() func() int { counter := session.DB("dbname").C("counter") cid := "counterid" return func() int { change := mgo.Change{ Update: bson.M{"$inc": bson.M{"seq": 1}}, Upsert: true, ReturnNew: true, } doc := struct{ Seq int }{} if _, err := counter.Find(bson.M{"_id": cid}).Apply(change, &doc); err != nil { panic(fmt.Errorf("get counter failed:", err.Error())) } log.Println("seq:", doc) return doc.Seq } }() wg := sync.WaitGroup{} // 創建10個 go routine模擬多線程環境 for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { _row := map[string]interface{}{ "_id": getNextSeq(), "username": fmt.Sprintf("name%2d", i), "telephone": fmt.Sprintf("tel%4d", rand.Int63n(1000))} if err := clt.Insert(_row); err != nil { log.Printf("insert %v failed: %v ", _row, err) } else { log.Printf("insert: %v success! ", _row) } wg.Done() }(i) } wg.Wait() }輸出:
2016/04/28 17:05:28 main.go:37: seq: {201} 2016/04/28 17:05:28 main.go:54: insert: map[_id:201 username:name 9 telephone:tel 410] success! 2016/04/28 17:05:28 main.go:37: seq: {204} 2016/04/28 17:05:28 main.go:37: seq: {203} 2016/04/28 17:05:28 main.go:37: seq: {202} 2016/04/28 17:05:28 main.go:37: seq: {206} 2016/04/28 17:05:28 main.go:37: seq: {205} 2016/04/28 17:05:28 main.go:54: insert: map[_id:202 username:name 5 telephone:tel 51] success! 2016/04/28 17:05:28 main.go:54: insert: map[_id:204 username:name 2 telephone:tel 551] success! 2016/04/28 17:05:28 main.go:54: insert: map[telephone:tel 821 _id:203 username:name 1] success! 2016/04/28 17:05:28 main.go:37: seq: {207} 2016/04/28 17:05:28 main.go:54: insert: map[_id:205 username:name 6 telephone:tel 320] success! 2016/04/28 17:05:28 main.go:54: insert: map[_id:206 username:name 4 telephone:tel 937] success! 2016/04/28 17:05:28 main.go:54: insert: map[_id:207 username:name 3 telephone:tel 758] success! 2016/04/28 17:05:28 main.go:37: seq: {208} 2016/04/28 17:05:28 main.go:54: insert: map[username:name 7 telephone:tel 148 _id:208] success! 2016/04/28 17:05:28 main.go:37: seq: {209} 2016/04/28 17:05:28 main.go:54: insert: map[_id:209 username:name 0 telephone:tel 216] success! 2016/04/28 17:05:28 main.go:37: seq: {210} 2016/04/28 17:05:28 main.go:54: insert: map[_id:210 username:name 8 telephone:tel 449] success!mongo查詢結果
db.test.find({_id:{$gt:200}}) { "_id" : 201, "username" : "name 9", "telephone" : "tel 410" } { "_id" : 202, "username" : "name 5", "telephone" : "tel 51" } { "_id" : 203, "username" : "name 1", "telephone" : "tel 821" } { "_id" : 204, "username" : "name 2", "telephone" : "tel 551" } { "_id" : 205, "username" : "name 6", "telephone" : "tel 320" } { "_id" : 206, "username" : "name 4", "telephone" : "tel 937" } { "_id" : 207, "username" : "name 3", "telephone" : "tel 758" } { "_id" : 208, "username" : "name 7", "telephone" : "tel 148" } { "_id" : 209, "username" : "name 0", "telephone" : "tel 216" } { "_id" : 210, "username" : "name 8", "telephone" : "tel 449" }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/18838.html
摘要:排序結果的條件修改器條件,用戶對匹配的文檔進行更新和必須指定一個布爾類型,表示是否刪除文檔和必須指定一個布爾類型,表示返回更新前的文檔還是更新后的文檔,默認是更新前的文檔。 本文所有內容以MongoDB 3.2 為基礎。 插入并保存文檔 插入是添加數據的基本方法。可以使用insert插入一個文檔: db.foo.insert({bar: baz}) 批量插入 使用批量插入,可以加快插入...
摘要:前言數據更新,中的,對任何數據庫而言都是最基本的操作。你并不能保證數據在被你讀出來到寫回去期間是否有別人已經改了數據庫中的記錄,這就是第一個風險,操作存在潛在的可能性會覆蓋掉別人更新過的數據。 前言 數據更新,CRUD中的U,對任何數據庫而言都是最基本的操作。看似簡單的更新操作中會藏著哪些坑?今天聊一聊這個話題。 在寫這個系列文章時,我會假設讀者已經對MongoDB有了最基礎的了解,因...
摘要:所以,兩個需要同時進行的更新會迅速接連完成,此過程不會破壞文檔最新的更新會取得勝利。可以使用原子性的更新修改器,指定對文檔中的某些字段進行更新。 上一篇文章:MongoDB指南---5、創建、刪除文檔下一篇文章:MongoDB指南---7、find簡介與查詢條件 文檔存入數據庫以后,就可以使用update方法來更新它。update有兩個參數,一個是查詢文檔,用于定位需要更新的目標文檔...
摘要:所以,兩個需要同時進行的更新會迅速接連完成,此過程不會破壞文檔最新的更新會取得勝利。可以使用原子性的更新修改器,指定對文檔中的某些字段進行更新。 上一篇文章:MongoDB指南---5、創建、刪除文檔下一篇文章:MongoDB指南---7、find簡介與查詢條件 文檔存入數據庫以后,就可以使用update方法來更新它。update有兩個參數,一個是查詢文檔,用于定位需要更新的目標文檔...
閱讀 3323·2021-11-08 13:12
閱讀 2765·2021-10-15 09:41
閱讀 1457·2021-10-08 10:05
閱讀 3303·2021-10-08 10:04
閱讀 2110·2021-09-29 09:34
閱讀 2478·2019-08-30 15:55
閱讀 2982·2019-08-30 15:45
閱讀 2589·2019-08-29 14:17