利用mgo,批量修改 mongodb 中的表记录

需求:

写一个版本升级脚本,脚本中要修改数据库结构。

上一个版本,数据库所有记录用一个叫“key”的字段作为key

升级后的版本,把key 写到_id 里面去。这样就可以作为唯一主键和 索引,从而提高性能。

 

困难点:

在网上找到的mgo,到数据库里面查到数据后,都是用struct来接受。这样我就要定义无数个struct,很明显不实际。

由于我现在要修改的东西是修改的是_id,所以无法用 update 来实现。要有这几步:

1、查记录

2、把key赋值给_id,同时删除key

3、把这个新记录插入表中

4、把原来的记录删除

经过阅读源码,发现struct并非唯一可以接受查询结果的方法,map也可以。如下是核心代码:

func handleSingleCollection(db *mgo.Database, collectionName string)  {
	fmt.Println("Handling collecitonName: " + collectionName)
	var docs []map[string]interface{}
	coll := db.C(collectionName)
	count, _ := coll.Count()
	fmt.Println("collecitonName total records count: ", count)
	coll.Find(bson.M{"key": bson.M{"$exists": true}}).Select(bson.M{}).All(&docs)
	fmt.Println("collecitonName handling records count: ", len(docs))
	for _, doc := range docs {
		doc["_id"] = doc["key"]
		delete(doc, "key")
		//
		coll.Insert(doc)
	}
	coll.RemoveAll(bson.M{"key": bson.M{"$exists": true}})
}

 

modified 20200929

又遇到一个场景,要修改一个非key字段,可以直接用update搞定。困难点在于,我需要访问里面一层的数据:

{

_id: ***,

object: {

    data: ***

  }

}

用上面写的map切片取出来,之后是都是相当于指针,object的类型其实也是map[string]interface {}

我就写了一个小函数,获取嵌套在里面的数据:

// 用map切片获取ducument的时候,doc的类型是map[string]interface {}
//                         doc[object]的类型也是map[string]interface {}
// 但doc[object] 是一个interface {} 指向了map[string]interface {}
// 所以这里用反射的方法,获取了doc[object] 里面的内容
// 用interface{}的方式返回,在外层再转化成具体的类型
func getValueFromObject(obj interface{}, key string) interface{} {
	v := reflect.ValueOf(obj)
	return v.MapIndex(reflect.ValueOf(key)).Interface()
}

外层取用的时候是这样的:

domainId := getValueFromObject(doc["obj"], "domainId").(int)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值