问题描述
设置
我使用MysqL启动了一个项目,因此,我的项目有一些帮助程序类型来帮助处理空值,包括在API上解组传入的数据,将数据输入到DB中,然后进行相反的操作,提取数据时从数据库中移出,并用上述数据响应API。
出于这个问题的目的,我们将处理代表字符的结构。
type Character struct {
MongoID primitive.ObjectID `bson:"_id" json:"-"`
ID uint64 `bson:"id" json:"id"`
Name string `bson:"name" json:"name"`
CorporationID uint `bson:"corporation_id" json:"corporation_id"`
AllianceID null.Uint `bson:"alliance_id" json:"alliance_id,omitempty"`
FactionID null.Uint `bson:"faction_id" json:"faction_id,omitempty"`
SecurityStatus float64 `bson:"security_status" json:"security_status"`
NotModifiedCount uint `bson:"not_modified_count" json:"not_modified_count"`
UpdatePriority uint `bson:"update_priority" json:"update_priority"`
Etag null.String `bson:"etag" json:"etag"`
CachedUntil time.Time `bson:"cached_until" json:"cached_until"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`
}
我要专门研究null.Uint
类型的AllianceID属性,该属性由以下结构表示:
// Uint is an nullable uint.
type Uint struct {
Uint uint
Valid bool
}
在使用JSON和MysqL的API设置中(即我的设置,但这不是唯一的),这种结构使我能够轻松处理“可为空”的值,而不必处理指针。我一直听说,最好避免使用除结构指针(切片,结构切片,结构映射等)以外的指针。如果您有原始类型(int,bool,float等),请尝试避免使用指向该原始类型的指针。
此类型具有MarshalJSON
,UnmarshalJSON
,Scan
和Value
之类的函数,这些函数内部具有利用Vaild属性确定要返回的值类型的逻辑。在此设置下,这确实非常有效。
问题
经过研究,我发现Mongo比关系数据库更适合我,但是由于Mongo Document(Schemaless)的流动性,我很难理解如何处理以下情况:一个字段可能会丢失,或者我在MysqL中拥有的属性通常会为null,并且可以轻松解组此结构的顶部并在逻辑上使用辅助函数,该属性已得到处理。另外,当我建立与Mongo的连接并从MysqL中拉出几行并从这些行中在Mongo中创建Documents时,BSON层会整理联盟ID的整个类型并将其粘贴在数据库中。
示例:
"alliance_id" : {
"uint" : NumberLong(99007760),"valid" : true
},
与MysqL中一样,实现Valuer接口的Value函数将被调用并返回99007760
,这就是数据库中的值。
另一种情况是有效为假。在MysqL中,这将意味着一个空值,并且在调用Value函数时,它将返回nil并且MysqL驱动程序将使用NULL
所以我的问题是我该怎么做?我是否需要从头开始并重建模型,并在应用程序中重做一些使用Valid属性并使用*Pointers
的逻辑,还是可以使用这些帮助程序类型来做我想做的事情。
我确实想说我已经尝试在bson包上实现Marshaller
和Unmarshaller
接口,并且文档中的alliane_id仍设置为该类型的json编码版本,因为我以上概述。我想指出这一点,以排除实现这些接口的任何建议。如果我要实现的目标与Mongo相反,请链接一些指南,这些指南可以帮助我实现我要实现的目标。
感谢所有可以提供帮助的人。
解决方法
处理此类可选字段的最简单方法是使用指针:
type Character struct {
ID *uint64 `bson:"id,omitempty" json:"id"`
Name string `bson:"name" json:"name"`
...
}
以上,如果ID
字段为非空,则将其写入。取消编组时,如果数据库记录具有值,则将其设置为非nil值。如果省略omitempty
标志,则封送此结构会将null
写入数据库。
对于字符串,如果为空,则可以使用omitempty
来完全省略该字段。如果要存储空字符串,请省略omitempty
。