在 Go 中从 MySQL 迁移到 Mongo 时处理 NULL

Dealing with NULLs when migrating from MySQL to Mongo in Go

设置

我使用 MySQL 开始了一个项目,因此,我的项目有一些帮助处理空值的帮助程序类型,无论是在 API 上解组传入数据时,还是将数据输入数据库时,然后与之相反,从数据库中提取数据并将所述数据响应到 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 属性 来确定return 是什么类型的值。这在这个设置下效果非常好。

问题

经过一些研究,我开始意识到 Mongo 比关系数据库更适合我,但是由于 Mongo 文档(无模式)的流动性,我很难理解如何处理可能缺少字段的场景,或者我在 MySQL 中的 属性 通常为 null 的情况,我可以轻松地解组此结构并在逻辑上使用辅助函数, 被处理。此外,当我设置与 Mongo 的连接并从 MySQL 中提取几行并从这些行中创建 Mongo 中的文档时,BSON 层正在编组 Alliance ID 的整个类型和将其粘贴到数据库中。

示例:

    "alliance_id" : {
        "uint" : NumberLong(99007760),
        "valid" : true
    },

在 MySQL 中,将调用实现 Valuer 接口的值函数,并且 return 99007760 就是数据库中的值。

另一种情况是 valid 为 false。在 MySQL 中,这意味着空值,当调用 Value 函数时,它将 return nil 并且 mysql 驱动程序将使用 NULL[=25= 填充字段]

所以我的问题是我该怎么做?我是否需要从头开始并重建我的模型并重做我的应用程序中利用 Valid 属性 和使用 *Pointers 的一些逻辑,或者我可以使用这些帮助程序类型做我想做的事情吗.

我确实想说我已经尝试在bson包上实现MarshallerUnmarshaller接口,文档中的alliane_id仍然设置为json 我上面概述的这种类型的编码版本。我想指出这一点以排除实施这些接口的任何建议。如果我试图实现的目标与 Mongo 的直觉相反,请 link 一些指南可以帮助我实现我正在尝试做的事情。

感谢所有对此提供帮助的人。

像这样处理可选字段的最简单方法是使用指针:

type Character struct {
    ID               *uint64             `bson:"id,omitempty" json:"id"`
    Name              string             `bson:"name" json:"name"`
    ...
}

上面的ID字段如果是non-nil就会被写入。解组时,如果数据库记录有值,它将被设置为 non-nil 值。如果省略 omitempty 标志,封送此结构会将 null 写入数据库。

对于字符串,如果字段为空,您可以使用 omitempty 完全省略该字段。如果要存储空字符串,请省略 omitempty.