在Go中从MySQL迁移到Mongo时处理NULL 设置问题

问题描述

设置

我使用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等),请尝试避免使用指向该原始类型的指针。

此类型具有MarshalJSONUnmarshalJSONScanValue之类的函数,这些函数内部具有利用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包上实现MarshallerUnmarshaller接口,并且文档中的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