Mgo库的常见坑总结
kevin · · 4049 次点击 · · 开始浏览mgo库是一个很好用的MongoDB驱动。对我们来说,主力数据库是MongoDB,因此这个驱动对我们来说也是非常重要的。但是,mgo库有些问题算是一些坑,这里我做了一些简单的整理。
一些关于bson.ObjectId的问题
ObjectId为空的判断
如果你看bson.ObjectId定义的话,它是一个string类型的数据。但是如果你直接定义一个结构,并且生成对象时,这个对象并不是这样的。
我们首先定义一个结构体:
typeHomestruct{IDbson.ObjectId`bson:"_id,omitempty"`Namestring`bson:"name"`}然后看看一个生成的内容
h:=Home{Name:"123"}fmt.Println(h.ID)结果是ObjectIdHex("")。换句话说,如果你是想判断一个结构体的ObjectId是否为空,使用h.ID == ""是一定会结果为false的。如果你想判断是否为空,正确的方式应该为:
h:=Home{Name:"123"}fmt.Println(h.ID)fmt.Println(h.ID.Hex()=="")正确的生成ObjectId
首先值得注意的是NewObjectIdWithTime(t time.Time)这个方法生成的ObjectId并不是唯一的,结果可能导致的是插入失败。最有效的方式是设定ObjectId对象支持omitempty属性,就像我上面生成的结构体一样,由数据库统一调配生成ObjectId。如果真的确实需要,可以选择NewObjctId()。
时间问题
之前看到有人问,为什么保存的时间进入到数据库中慢了8个小时呢?原因是在保存进入MongoDB时,数据是按照UTC时间(不懂什么是UTC?看这里)进行的保存,但是取出是按照当前时区来取出。那么问题来了,我的客户如果不都是国人,我怎么保存时间呢?目前我们采用了两种方式来确定数据库的保存时间。一种是Unix时间戳,这个是不受到时区的影响的,由前端格式化为对应的时区时间;另外一种则是需要在额外的对从MongoDB数据库中取出的数据进行额外的时区校准,简单来说可以这样:
typeHomestruct{IDbson.ObjectId`bson:"_id,omitempty"`Namestring`bson:"name"`InsertTimetime.Time`bson:"insert_time"`}funcmain(){sess,_:=mgo.Dial("127.0.0.1")c:=sess.DB("test").C("home")h:=Home{Name:"123",InsertTime:time.Now()}c.Upsert(bson.M{"name":"123"},h)c.Find(bson.M{"name":"123"}).One(&h)fmt.Println(h.InsertTime.Format("2006年01月02日 15:04:05"))tz,_:=time.LoadLocation("America/New_York")fmt.Println(h.InsertTime.In(tz).Format("2006年01月02日 15:04:05"))}更高效的使用Session
在MongoDB中合理使用Session可以更高效的操作数据库,做法是在之前进行一次Copy操作:
sessionCopy:=mongoSession.Copy()defersessionCopy.Close()collection:=sessionCopy.DB(TestDatabase).C("buoy_stations")log.Printf("RunQuery : %d : Executing\n",query)// Retrieve the list of stations.varbuoyStations[]BuoyStationerr:=collection.Find(nil).All(&buoyStations)iferr!=nil{log.Printf("RunQuery : ERROR : %s\n",err)return}log.Printf("RunQuery : %d : Count[%d]\n",query,len(buoyStations))另外值得一提的是MongoDB本身,目前我们已经提升到了MongoDB 3.0+版本,优势是相对之前版本的WiredTiger引擎比较令人印象深刻(如果有条件可以选择最新的3.2版本)。大家对之前MongoDB中索引建立的痛苦有印象,这个现象在WiredTiger引擎中也有所改进。更多的改进可以在WiredTiger的官网和MongoDB的性能白皮书中了解更多。最后,当然,我仍然不建议在非严重必要情况下创建多余索引,这对MongoDB的性能和资源消耗都有较大影响。
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
mgo库是一个很好用的MongoDB驱动。对我们来说,主力数据库是MongoDB,因此这个驱动对我们来说也是非常重要的。但是,mgo库有些问题算是一些坑,这里我做了一些简单的整理。
一些关于bson.ObjectId的问题
ObjectId为空的判断
如果你看bson.ObjectId定义的话,它是一个string类型的数据。但是如果你直接定义一个结构,并且生成对象时,这个对象并不是这样的。
我们首先定义一个结构体:
typeHomestruct{IDbson.ObjectId`bson:"_id,omitempty"`Namestring`bson:"name"`}然后看看一个生成的内容
h:=Home{Name:"123"}fmt.Println(h.ID)结果是ObjectIdHex("")。换句话说,如果你是想判断一个结构体的ObjectId是否为空,使用h.ID == ""是一定会结果为false的。如果你想判断是否为空,正确的方式应该为:
h:=Home{Name:"123"}fmt.Println(h.ID)fmt.Println(h.ID.Hex()=="")正确的生成ObjectId
首先值得注意的是NewObjectIdWithTime(t time.Time)这个方法生成的ObjectId并不是唯一的,结果可能导致的是插入失败。最有效的方式是设定ObjectId对象支持omitempty属性,就像我上面生成的结构体一样,由数据库统一调配生成ObjectId。如果真的确实需要,可以选择NewObjctId()。
时间问题
之前看到有人问,为什么保存的时间进入到数据库中慢了8个小时呢?原因是在保存进入MongoDB时,数据是按照UTC时间(不懂什么是UTC?看这里)进行的保存,但是取出是按照当前时区来取出。那么问题来了,我的客户如果不都是国人,我怎么保存时间呢?目前我们采用了两种方式来确定数据库的保存时间。一种是Unix时间戳,这个是不受到时区的影响的,由前端格式化为对应的时区时间;另外一种则是需要在额外的对从MongoDB数据库中取出的数据进行额外的时区校准,简单来说可以这样:
typeHomestruct{IDbson.ObjectId`bson:"_id,omitempty"`Namestring`bson:"name"`InsertTimetime.Time`bson:"insert_time"`}funcmain(){sess,_:=mgo.Dial("127.0.0.1")c:=sess.DB("test").C("home")h:=Home{Name:"123",InsertTime:time.Now()}c.Upsert(bson.M{"name":"123"},h)c.Find(bson.M{"name":"123"}).One(&h)fmt.Println(h.InsertTime.Format("2006年01月02日 15:04:05"))tz,_:=time.LoadLocation("America/New_York")fmt.Println(h.InsertTime.In(tz).Format("2006年01月02日 15:04:05"))}更高效的使用Session
在MongoDB中合理使用Session可以更高效的操作数据库,做法是在之前进行一次Copy操作:
sessionCopy:=mongoSession.Copy()defersessionCopy.Close()collection:=sessionCopy.DB(TestDatabase).C("buoy_stations")log.Printf("RunQuery : %d : Executing\n",query)// Retrieve the list of stations.varbuoyStations[]BuoyStationerr:=collection.Find(nil).All(&buoyStations)iferr!=nil{log.Printf("RunQuery : ERROR : %s\n",err)return}log.Printf("RunQuery : %d : Count[%d]\n",query,len(buoyStations))另外值得一提的是MongoDB本身,目前我们已经提升到了MongoDB 3.0+版本,优势是相对之前版本的WiredTiger引擎比较令人印象深刻(如果有条件可以选择最新的3.2版本)。大家对之前MongoDB中索引建立的痛苦有印象,这个现象在WiredTiger引擎中也有所改进。更多的改进可以在WiredTiger的官网和MongoDB的性能白皮书中了解更多。最后,当然,我仍然不建议在非严重必要情况下创建多余索引,这对MongoDB的性能和资源消耗都有较大影响。