如何使用 mgo 在单个集合中处理多种类型

How to work with multiple types in single collection with mgo

我是 golang 的新手,尝试使用 mongodb 作为后备数据库编写一个简单的事件源用户管理 webapi。现在我有了用户,它看起来像这样:

type User struct {
Id       bson.ObjectId `json:"id" bson:"_id"`
UserName string        `json:"username" bson:"username"`
Email    string        `json:"email" bson:"email"`
PwdHash  string        `json:"pwd_hash" bson:"pwd_hash"`
FullName string        `json:"fullname" bson:"fullname"`
}

和三个事件,发生在用户身上,当有人使用 api:

type UserCreatedEvent struct {
    UserId         bson.ObjectId `json:"id" bson:"_id"`
    //time when event was issued
    CreatedEpoch   time.Time     `json:"created_epoch" bson:"created_epoch"`
    //id of user that made a change
    IssuedByUserId bson.ObjectId `json:"issuedby_userid" bson:"issuedby_userid"`
}

type UserDeletedEvent struct {
    UserId         bson.ObjectId `json:"id" bson:"_id"`
    CreatedEpoch   time.Time     `json:"created_epoch" bson:"created_epoch"`
    //id of user that made a change
    IssuedByUserId bson.ObjectId `json:"issuedby_userid" bson:"issuedby_userid"`
}

type UserUpdatedEvent struct {
    UserId         bson.ObjectId `json:"id" bson:"_id"`
    CreatedEpoch   time.Time     `json:"created_epoch" bson:"created_epoch"`
    //id of user that made a change
    IssuedByUserId bson.ObjectId `json:"issuedby_userid" bson:"issuedby_userid"`
    ChangedFieldName     string  `json:"changed_field_name" bson:"changed_field_name"`
    NewChangedFieldValue string  `json:"new_changed_field_value" bson:"new_changed_field_value"`
}

现在我无法从数据库中保存和检索事件。问题是我想将它们存储在一个集合中,这样我就有了完整的用户修改历史。但我找不到如何将事件类型名称正确存储为 mongo 文档字段,然后在搜索中使用它。执行此操作的惯用方法是什么?

如有任何帮助,我将不胜感激。

非关系数据库的优点在于,有一点冗余是可以的,而且检索速度更快,因为您不需要将它们连接在一起。您可以以对您和您的数据有意义的任何方式将底部三个对象添加为 User 上的属性。那么你也不需要在这些对象上存储 UserId

如果您需要快速搜索 Events,您可以创建另一个集合来保存它们。您将插入到两个集合中,但检索 times/logic 写起来应该很漂亮 good/easy。

你的新 Event 应该是这样的:

type UserEventType int

const (
    Created UserEventType = iota
    Deleted
    Updated
)

type UserEvent struct {
    UserId               bson.ObjectId `json:"id" bson:"_id"`
    CreatedEpoch         time.Time     `json:"created_epoch" bson:"created_epoch"`
    //id of user that made a change
    IssuedByUserId       bson.ObjectId `json:"issuedby_userid" bson:"issuedby_userid"`
    ChangedFieldName     string        `json:"changed_field_name,omitempty" bson:"changed_field_name,omitempty"`
    NewChangedFieldValue string     `json:"new_changed_field_value,omitempty" bson:"new_changed_field_value,omitempty"`
    EventType            UserEventType `json:"user_event_type" bson:"user_event_type"`
}

请注意根据事件类型可选字段上的 omitempty

您真的不应该将不同的对象存储在同一个集合中。这是 Mongo 文档中的一行:

MongoDB stores documents in collections. Collections are analogous to tables in relational databases.

如果您不熟悉关系数据库,table 基本上代表一种类型的对象。