英文:
How can I assign a null value to date field using mongo go driver instead of Date(-62135596800000)
问题
我有两个MongoDB服务器。我使用mongo go驱动程序从其中一个服务器接收数据。接收到的数据有一个日期字段,该字段始终为null
。然后在我的代码中,我可能会将其更改为其他日期,也可能保持为null
并将接收到的数据放入另一个服务器。
问题是,当我提交数据时,时间字段变为Date(-62135596800000)
,而不是null
。
我尝试过分配time.Time{}
,下面的代码也没有解决问题。
t, err := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:01Z")
if err != nil {
fmt.Println(err)
}
retrieved[i].SessionEndedDateUTC = t
每次我都会得到Date(-62135596800000)
,即使我检索数据并在不修改的情况下进行插入更新。
英文:
I have two MongoDB servers. From one I receive data using mongo go driver. The received data has one date field which is always null
. Then in my code I may or may not change it to some other date or leave it as null
and put the received data to the other server.
The problem is that when I post the data, the time field turns to
> Date(-62135596800000) instead of null.
I have tried to assign time.Time{}
and the code below didn't solve the problem as well.
t, err := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:01Z")
if err != nil {
fmt.Println(err)
}
retrieved[i].SessionEndedDateUTC = t
Everytime I get Date(-62135596800000)
instead of null, even if I retrieve the data and upsert it without modification.
答案1
得分: 5
在Go语言中,time.Time
是一个结构体,不能为nil
值。它有一个零值(即所有结构字段都具有它们的零值),但是这个零值对应于MongoDB的ISODate("0001-01-01T00:00:00Z")
,而不是MongoDB的null
值。
如果你的字段是time.Time
类型,你不能将任何值设置给它以得到MongoDB的null
值。
最简单的解决方案是改用指向time.Time
的指针类型,即*time.Time
。如果你将该字段保留为Go的nil
值,它将在MongoDB中变为null
。
如果你不能或不想使用*time.Time
,仍然有一个"变通"方法:声明两个字段,一个是你的"常规"的time.Time
类型,使用结构标签将其排除在MongoDB之外。然后添加另一个类型为*time.Time
的字段,并将其映射到MongoDB。编写自定义的编组/解组逻辑,当编组时,根据原始字段更新这个额外的字段,或者在解组时,根据额外的字段设置原始字段。
以下是一个示例:
type User struct {
CreatedAt time.Time `bson:"-"`
PCreatedAt *time.Time `bson:"created"`
}
func (u *User) GetBSON() (interface{}, error) {
if u.CreatedAt.IsZero() {
u.PCreatedAt = nil
} else {
u.PCreatedAt = &u.CreatedAt
}
return u, nil
}
func (u *User) SetBSON(raw bson.Raw) (err error) {
if err = raw.Unmarshal(u); err != nil {
return
}
if u.PCreatedAt == nil {
u.CreatedAt = time.Time{}
} else {
u.CreatedAt = *u.PCreatedAt
}
return
}
解释:
User.CreatedAt
保存了你可以使用(读取/写入)的time.Time
值。这个字段在MongoDB中被排除。
有一个指针字段User.PCreatedAt
,它被映射到MongoDB中的created
属性。
当一个User
对象被编组(保存到MongoDB)时,会调用GetBSON()
方法。如果CreatedAt
是零值,则将PCreatedAt
设置为nil
,这将在MongoDB中变为null
。否则,使用非零的时间戳。
当一个User
对象被解组(从MongoDB加载)时,会调用SetBSON()
方法。它检查PCreatedAt
是否为nil
(对应于MongoDB的null
),如果是,则将CreatedAt
设置为零值。否则,使用从MongoDB中检索到的时间戳。
相关/类似的问题:
https://stackoverflow.com/questions/42342943/accesing-mongodb-from-go/42343810#42343810
英文:
In Go time.Time
is a struct which cannot have a nil
value. It has a zero value (which is all struct fields having their zero values), but this zero value corresponds to MongoDB ISODate("0001-01-01T00:00:00Z")
and not to the MongoDB null
value.
If your field is of type time.Time
, you cannot set any value to it to end up MongoDB null
value.
The simplest solution is to use a field of type pointer to time.Time
instead, that is *time.Time
. If you leave or set this field to Go nil
, it will end up as null
in MongoDB.
If you can't or don't want to use *time.Time
, there is still a "workaround": declare 2 fields, one is of your "regular" time.Time
type, and use a struct tag to exclude this from MongoDB. And add another field of type *time.Time
, and make this mapped to MongoDB. And write a custom marshaling / unmarshaling logic, which when marshaling would update this extra field based on the original, or would set the original based on the extra when unmarshaling.
This is an example how it could look like:
type User struct {
CreatedAt time.Time `bson:"-"`
PCreatedAt *time.Time `bson:"created"`
}
func (u *User) GetBSON() (interface{}, error) {
if u.CreatedAt.IsZero() {
u.PCreatedAt = nil
} else {
u.PCreatedAt = &u.CreatedAt
}
return u, nil
}
func (u *User) SetBSON(raw bson.Raw) (err error) {
if err = raw.Unmarshal(u); err != nil {
return
}
if u.PCreatedAt == nil {
u.CreatedAt = time.Time{}
} else {
u.CreatedAt = *u.PCreatedAt
}
return
}
Explanation:
User.CreatedAt
holds the time.Time
value which you can work with (read / write). This field is excluded from MongoDB.
There is a pointer User.PCreatedAt
field which is mapped to the created
property in MongoDB.
When a User
is marshaled (saved to MongoDB), GetBSON()
is called. If CreatedAt
is the zero value, sets PCreatedAt
to nil
which will end up as null
in MongoDB. Else sets / uses the non-zero timestamp.
When a User
is unmarshaled (loaded from MongoDB), SetBSON()
is called. This checks if PCreatedAt
is nil
(which corresponds to MongoDB null
), and if so, sets CreatedAt
to its zero value. Else uses the timestamp retrieved from MongoDB.
Related / similar questions:
https://stackoverflow.com/questions/42342943/accesing-mongodb-from-go/42343810#42343810
答案2
得分: 0
行为
在内部,Date对象以一个64位整数的形式存储,表示自Unix纪元(1970年1月1日)以来的毫秒数,这导致了一个可表示的日期范围,大约可以追溯到过去和未来的290亿年。
请参阅https://docs.mongodb.com/manual/reference/method/Date/
英文:
mongodb doc
Behavior
Internally, Date objects are stored as a 64 bit integer representing the number of milliseconds since the Unix epoch (Jan 1, 1970), which results in a representable date range of about 290 millions years into the past and future
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论