当前位置: 首页 > 面试题库 >

在Go中的mongodb驱动程序中进行比较以及可能以其他语言和其他数据库进行比较时的时间精度问题

万知
2023-03-14
问题内容

我正在学习Go和Mongodb,目前正在使用alpha官方mongodb驱动程序。尽管它是alpha版本,但我认为它对于基本用法还是很有用的。但是在这个数据库驱动程序中,我在时间转换上遇到了一个有趣的问题。

基本上,我创建了一个自定义类型的struct对象,并将其编组为bson文档,然后将bson文档转换回struct对象。

//check github.com/mongodb/mongo-go-driver/blob/master/bson/marshal_test.go
func TestUserStructToBsonAndBackwards(t *testing.T) {
u := user{
    Username:          "test_bson_username",
    Password:          "1234",
    UserAccessibility: "normal",
    RegisterationTime: time.Now(), //.Format(time.RFC3339), adding format result a string
}

//Struct To Bson
bsonByteArray, err := bson.Marshal(u)
if err != nil {
    t.Error(err)
}
//.UnmarshalDocument is the same as ReadDocument
bDoc, err := bson.UnmarshalDocument(bsonByteArray)
if err != nil {
    t.Error(err)
}
unameFromBson, err := bDoc.LookupErr("username")
//so here the binding is working for bson object too, the bind field named username ratherthan Username
if err != nil {
    t.Error(err)
}
if unameFromBson.StringValue() != "test_bson_username" {
    t.Error("bson from user struct Error")
}

//Bson Doc to User struct
bsonByteArrayFromDoc, err := bDoc.MarshalBSON()
if err != nil {
    t.Error(err)
}

var newU user
err = bson.Unmarshal(bsonByteArrayFromDoc, &newU)
if err != nil {
    t.Error(err)
}

if newU.Username != u.Username {
    t.Error("bson Doc to user struct Error")
}

//here we have an issue about time format.
if newU != u {
    log.Println(newU)
    log.Println(u)
    t.Error("bson Doc to user struct time Error")
}
}

但是,由于我的struct对象具有一个时间字段,因此结果struct对象包含的时间值比原始对象的时间值精度低。然后比较失败。

=== RUN   TestUserStructToBsonAndBackwards
{test_bson_username 1234     0001-01-01 00:00:00 +0000 UTC   2018-08-28 23:56:50.006 +0800 CST 0001-01-01 00:00:00 +0000 UTC normal }
{test_bson_username 1234     0001-01-01 00:00:00 +0000 UTC   2018-08-28 23:56:50.006395949 +0800 CST m=+0.111119920 0001-01-01 00:00:00 +0000 UTC normal }
--- FAIL: TestUserStructToBsonAndBackwards (0.00s)
    model.user_test.go:67: bson Doc to user struct time Error

因此,我想问很多问题。

  1. 在这种情况下如何正确比较时间?

  2. 在数据库中存储时间以避免这种精度问题的最佳方法是什么?我认为数据库中的时间不应为字符串。

  3. 这是数据库驱动程序错误吗?


问题答案:

BSON中的时间以自Unix纪元(spec)以来的UTC毫秒表示。Go中的时间值具有纳秒级精度。

为了往返时间,通过BSON编组的时间值,请使用自Unix时代以来截断为毫秒的时间:

func truncate(t time.Time) time.Time {
    return time.Unix(0, t.UnixNano()/1e6*1e6)
}

...

u := user{
    Username:          "test_bson_username",
    Password:          "1234",
    UserAccessibility: "normal",
    RegisterationTime: truncate(time.Now()), 
}

您还可以使用Time.Truncate方法:

u := user{
    Username:          "test_bson_username",
    Password:          "1234",
    UserAccessibility: "normal",
    RegisterationTime:  time.Now().Truncate(time.Milliseconds),
}

这种方法依赖于Unix纪元和Go零时间相差整数毫秒的事实。



 类似资料:
  • 问题内容: 如何检查数据库中是否存在Blob的重复项。我的数据库中有文档表,但是我不确定如何检查其中一个是否重复。我知道您应该使用dbms_lob.compare函数,但是在阅读了有关该主题的一些线程和文章之后,我仍然不明白这一点。 Documents表具有document_id列和data(blob)列。如何检查document_id = 1是否重复? 问题答案: “如果dbms_lob.com

  • 问题内容: 我想知道是否存在以下有效用例: 接受类型为where 的集合似乎是一种常见的模式(请参见Collections中的许多示例)。 但是,与基类进行比较时,在技术上似乎无法履行合同,因为无法确保另一类不会通过矛盾的比较来扩展基数。考虑以下示例: 我们有两个类,它们使用不遵循共同规则的比较进行扩展(如果存在共同规则,则几乎可以肯定在中实现)。但是,下面的破碎类将被编译: 只接受不安全吗?还是

  • 请原谅我在这里缺乏理解,因为我已经进入了三天的冬眠期。 我正在尝试在一个实体上添加验证,这需要将它们与另一个实体进行比较。 例如,以一个人为例。一个人可以有许多身体部位,但最多有两个手臂类型的身体部位(变异除外)。为了验证这一点,在插入新的车身部件时,我需要将其与给定人员的其他车身部件进行比较,并验证该类型的最大值是否已经达到。 我一直在研究Hibernate提供的约束/验证内容,但似乎没有一个涵

  • 首先要明确一点的是,没有最好,只有最合适。前端框架并不是所谓 注:本文一些数据收集时间为16-12-31 因为大部分教程都是付费的,所以教程数量的多少在侧面反映了框架的市场需求,如果框架冷门用的人不多,那必然不会有人去为其开发教程。

  • 我想用Java做一个程序来比较两个三角形。比较角度的顺序无关紧要,我知道我可以用语句来做,但有没有其他更有效的方法来比较3个角度和另外3个角度,因为三角形旋转并不重要,因为完全相同?(Java语言)

  • 问题内容: 为了比较两个浮点数(float64)在Go中的相等性,我对IEEE 754和浮点数的二进制表示的肤浅理解使我认为这是一个很好的解决方案: 问题是:与旧的hack 相比,这是一种更通用,更精确,更有效的方法来比较两个任意大或小的浮点数以“几乎相等” 吗?我的理由是,如果一个二进制表示形式仅允许一位差异,那么除了严格的相等性(显然可以如注释中所指出的那样)之外,比较的数字当然不能再相等了(