Golang 中操作 Mongo Update 的方法
MongoDB 中有一种时间格式数据 ISODate,参考如下:
如果在 Golang 中查询这条记录,Golang用什么类型的变量来保存呢?
查找 ISODate 时间字段
在 Golang 中可以使用 time.Time 数据类型来保存 MongoDB 中的 ISODate 时间。
type Model struct {
Id bson.ObjectId `bson:"_id,omitempty"`
Time time.Time `bson:"time"`
}
m := Model{}
err := c.Find(bson.M{"_id": bson.ObjectIdHex("572f3c68e43001d2c1703aa7")}).One(&m)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", m)
// output: {Id:ObjectIdHex("572f3c68e43001d2c1703aa7") Time:2015-07-08 17:29:14.002 +0800 CST}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
从输出中可以看到 Golang 输出的时间格式是 CST 时区,Golang 在处理的过程中将 ISO 时间转换成了 CST 时间,从时间面板上来看也比 MongoDB 中的快上 8 个小时,这个是正常的。
那么 Golang 做插入操作和或者时间比较操作的时候需要自己转换时间戳吗?答案是不需要的,来看下插入的例子。
插入时间
重新插入一条记录,记录的Time字段为当前时间,在golang中可以通过time.Now获取当前时间,查看输出可以看到是CST的时间格式
now := time.Now()
fmt.Printf("%+v\n", now)
// output: 2016-05-12 14:34:00.998011694 +0800 CST
err = c.Insert(Model{Time: now})
if err != nil {
panic(err)
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
查看 MongoDB 中的记录
插入当前时间到 MongoDB:
可以看到存储到 MongoDB 中时间的自动转换为了 ISO 时间,时间少了 8 个小时。小结一下就是 Golang 和 MongoDB 中的时间交互不需要考虑额外的东西,因为驱动都进行了转换。
时间字符串转成 time.Time
有时我们会将 time.Time 的时间以字符串的形式存储,那么要和 MongoDB 交互的时候就需要转换 time.Time 格式
// 时间字符串转到到time.Time格式
// 使用time.Parse方法进行转换
timeString := "2016-05-12 14:34:00.998011694 +0800 CST"
t, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", timeString)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", t)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
代码中比较难理解的就是 time.Parse 的第一个参数,这个其实是 Golang 当中的定义,详细看下 time.Time.String() 的源码就会明白了。
这篇博客主要记录下 Golang 中引入 Mongo 数据库对 Mongo 的修改操作的方法。
使用gopkg.in/mgo.v2库操作,修改操作主要使用mongodb中Collection对象的Update、UpdateAll、UpdateId、Upsert、UpsertId方法。
统一封装下getDB方法
package main
import (
"fmt"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// get mongodb db
func getDB() *mgo.Database {
session, err := mgo.Dial("127.0.0.1:27017")
if err != nil {
panic(err)
}
session.SetMode(mgo.Monotonic, true)
db := session.DB("test")
return db
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
Update修改单条记录
func (c *Collection) Update(selector interface{}, update interface{}) error
- 1
和mysql不同,Update函数只能用来修改单条记录,即使条件能匹配多条记录,也只会修改第一条匹配的记录。
selector := bson.M{"_id": bson.ObjectIdHex("56fdce98189df8759fd61e5b")}
data := bson.M{"age": 21}
err := getDB().C("user").Update(selector, data)
if err != nil {
panic(err)
}
- 1
- 2
- 3
- 4
- 5
- 6
类似于mongodb语法:
db.getCollection('user').update(
{ "_id": ObjectId("56fdce98189df8759fd61e5b") },
{ "age": 21}
)
- 1
- 2
- 3
- 4
这边有一个小坑,就是这种写法的修改数据会更新整个文档为 {“age”: 21},而不是只更新age的值。
更新前数据:
{
"_id" : ObjectId("56fdce98189df8759fd61e5b"),
"name" : "Tom",
"age" : 20
}
更新后数据:
{
"_id" : ObjectId("56fdce98189df8759fd61e5b"),
"age" : 21
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
如果需要只更新age的值,则需要使用$set关键词:
selector := bson.M{"_id": bson.ObjectIdHex("571de968a99cff2c68264807")}
data := bson.M{"$set": bson.M{"age": 21}}
err := getDB().C("user").Update(selector, data)
if err != nil {
panic(err)
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
如果更新的数据不存在,则会报一个not found的错误:
// 更新不存在的数据
selector := bson.M{"_id": bson.ObjectIdHex("16fdce98189df8759fd61e5b")}
data := bson.M{"age": 21}
err := getDB().C("user").Update(selector, data)
if err != nil {
fmt.Println(err == mgo.ErrNotFound)
// output: true
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
由于Update只能更新一条数据,如果需要批量更新则需要使用UpdateAll函数
UpdateAll批量更新
func (c *Collection) UpdateAll(selector interface{}, update interface{}) (info *ChangeInfo, err error)
- 1
- 2
selector := bson.M{"name": "Tom"}
data := bson.M{"$set": bson.M{"age": 22}}
changeInfo, err := getDB().C("user").UpdateAll(selector, data)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", changeInfo)
// output: &{Updated:2 Removed:0 UpsertedId:<nil>}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
UpdateId根据Id更新
和Update函数类似,就是条件直接换成了objectid,这个使用也挺频繁的。
func (c *Collection) UpdateId(id interface{}, update interface{}) error
类似
err := collection.Update(bson.M{"_id": id}, update)
- 1
- 2
- 3
id := bson.ObjectIdHex("571de968a99cff2c68264807")
data := bson.M{"$set": bson.M{"age": 30}}
err := getDB().C("user").UpdateId(id, data)
if err != nil {
panic(err)
}
- 1
- 2
- 3
- 4
- 5
- 6
Upsert更新或者插入数据
这个函数就是如果数据存在就更新,否则就新增一条记录。这个函数也挺常用的。
func (c *Collection) Upsert(selector interface{}, update interface{}) (info *ChangeInfo, err error)
- 1
selector := bson.M{"key": "max"}
data := bson.M{"$set": bson.M{"value": 30}}
changeInfo, err := getDB().C("config").Upsert(selector, data)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", changeInfo)
// 首次执行output: &{Updated:0 Removed:0 UpsertedId:ObjectIdHex("571df02ea99cff2c6826480a")}
// 再次执行output: &{Updated:1 Removed:0 UpsertedId:<nil>}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
UpsertId按照更新或者插入数据
func (c *Collection) UpsertId(id interface{}, update interface{}) (info *ChangeInfo, err error)
类似
info, err := collection.Upsert(bson.M{"_id": id}, update)
- 1
- 2
- 3
id := bson.ObjectIdHex("571df02ea99cff2c6826480b")
data := bson.M{"$set": bson.M{"key": "max", "value": 30}}
changeInfo, err := getDB().C("config").UpsertId(id, data)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", changeInfo)
// 首次执行output: &{Updated:0 Removed:0 UpsertedId:ObjectIdHex("571df02ea99cff2c6826480b")}
// 再次执行output: &{Updated:1 Removed:0 UpsertedId:<nil>}
Golang 中操作 Mongo Update 的方法的更多相关文章
- JQuery中操作Css样式的方法
JQuery中操作Css样式的方法//1.获取和设置样式 $("#tow").attr("class")获取ID为tow的class属性 $("#tw ...
- 【转发】JQuery中操作Css样式的方法
JQuery中操作Css样式的方法 //1.获取和设置样式 $("#tow").attr("class")获取ID为tow的class属性 $("#t ...
- 在Python中操作文件之truncate()方法的使用教程
在Python中操作文件之truncate()方法的使用教程 这篇文章主要介绍了在Python中操作文件之truncate()方法的使用教程,是Python入门学习中的基础知识,需要的朋友可以参考下 ...
- 六、golang中的结构体和方法、接口
结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...
- android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法
MONO 调用一个线程操作UI 然后报Only the original thread that created a view hierarchy can touch its views.错误 goo ...
- Flex中操作XML的E4X方法
用于处理 XML 的 E4X 方法 Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本 ECMAScript for XML 规范定义了一组用于使用 XML 数据的类 ...
- 关于js中操作数组的一些方法
网上找的通篇看了一遍讲的很透收藏了! 转自(https://www.cnblogs.com/blogs-8888/p/6518683.html) 1.锁定数组的长度(让数组的长度变成只读). 1 2 ...
- vue中操作Dom节点的方法
1.vue中ref操作dom节点 <template> <div id="app"> <div </div> <button @cl ...
- 【golang】golang中结构体的初始化方法(new方法)
准备工作: 定义结构体:Student import ( "fmt" "reflect") type Student struct { StudentId st ...
随机推荐
- Leet Code OJ 226. Invert Binary Tree [Difficulty: Easy]
题目: Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 思路分析: 题意是将二叉树全部左右子数 ...
- angularjs中响应回车事件
下面这个示例在输入框键入回车键或者点击按钮时,将输入框的值置为"Hello World!":(黄色背景内容为响应回车事件涉及到的代码) <html ng-app=" ...
- 转:不在同一个服务器上的数据库之间的数据操作(oracle/sql server的对比)
如何操做不在同一个数据库中的数据操作: 一.对于SQL server来讲: 1.采用创建链接服务器的方式: (1).创建链接服务器 exec sp_addlinkedserver ...
- Arrays.asList的用法
使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportOperationException异常说明: ...
- SqlServer字段说明查询及快速查看表结构
SqlServer字段说明查询 SELECT t.[name] AS 表名,c.[name] AS 字段名,cast(ep.[value] )) AS [字段说明] FROM sys.tables A ...
- jquery remove()不兼容问题解决方案
jquery remove()不兼容问题解决方案 CreationTime--2018年7月27日10点19分 Author:Marydon 1.情景展示 点击关闭,将这个div移除掉 源码展示 ...
- LOL 战斗力查询
LOL(英雄联盟) 战斗力查询 接口:http://lolbox.duowan.com/playerDetail.php?serverName=serverName&playerName=pl ...
- javascript 新知识
document.compatMode 属性 BackCompat: Standards-compliant mode is not switched on. (Quirks Mode) 标准模式 ...
- android使用achartengine 实现折线图
折线图的实现分为下边几个步骤: 1.第一步:数据的准备 XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset(); XYSeri ...
- unity模型任意无限切割插件
概述 3d模型的任意切割一直是游戏开发里的一个很大的问题,模型切割的关键点就只有生成横切面的新顶点以及切口纹理的缝合,理论上解决了这两点,就近乎可以做到以假乱真的程度了.本篇文章就这两点进行描述 详细 ...