首页 > 解决方案 > 从 yaml 到 go-gorm 的自引用 uuid

问题描述

我正在尝试从 yaml 文件创建一个自引用的 many2many。引用保存为 uuid,所以我试过这个:

type Activity struct {
    ID                uuid.UUID    `yaml:"id" gorm:"type:uuid;primaryKey"`
    ActivityStreamID  uuid.UUID    `yaml:"stream" gorm:"type:uuid"`
    MaturityLevelID   uuid.UUID    `yaml:"level" gorm:"type:uuid"`
    Title             string       `yaml:"title"`
    Benefit           string       `yaml:"benefit"`
    ShortDescription  string       `yaml:"shortDescription"`
    LongDescription   string       `yaml:"longDescription" gorm:"type:text"`
    Results           StringArray  `yaml:"results" gorm:"type:text[]"`
    Metrics           StringArray  `yaml:"metrics" gorm:"type:text[]"`
    Costs             string       `yaml:"costs"`
    Personnel         StringArray  `yaml:"personnel" gorm:"type:text[]"`
    Notes             string       `yaml:"notes"`
    RelatedActivities []*Activities `yaml:"relatedActivities" gorm:"type:uuid;many2many:related_activities"`
    Type              string       `yaml:"type"`
    Questions         []Question   `gorm:"type:uuid;many2many:activity_questions;"`
}

问题是,虽然这看起来像是 go-gorm 的正确用法,但它并没有在 yaml 中正确解组:

2020/10/31 21:10:28 Problem unmarshaling example.yml: yaml: unmarshal errors:
  line 47: cannot unmarshal !!str `e17d573...` into example.Activity
exit status 1

切换RelatedActivities到 useuuid.UUID时,yaml 工作正常,但在 go-gorm 中无法正确识别:

...
RelatedActivities []*uuid.UUID `yaml:"relatedActivities" gorm:"type:uuid;many2many:related_activities"`
...

我在这个例子中使用 sqlite:

2020/10/31 21:11:51 .../populateDB.go:60 row value misused
[0.063ms] [rows:0] INSERT INTO `activities` (`id`,`activity_stream_id`,`maturity_level_id`,`title`,`benefit`,`short_description`,`long_description`,`results`,`metrics`,`costs`,`personnel`,`notes`,`related_activities`,`type`,`questions`) VALUES ("a573c126-b3e3-45fb-a9d1-d94c8158cf60","1a7ad26d-9e48-411e-95a6-3be79e1b90ea","1cb6e197-ca82-45ec-a65b-0ecbdd784720","Enforce timely patch management","Clear view","Actively.....","Develop ...","{}","{}","","{}","",("93dff7be-5f95-4f8d-87d2-4f4261002508","2bf0e192-a904-444b-8a2f-38c33256e80a","0082a76b-1a37-44d9-ab04-43bd2168e13d"),"Activity",(NULL))
2020/10/31 21:11:51 row value misused
...

很明显,这是因为自引用是 中的一个列表("93dff7be-5f95-4f8d-87d2-4f4261002508","2bf0e192-a904-444b-8a2f-38c33256e80a","0082a76b-1a37-44d9-ab04-43bd2168e13d"),但不是在新的 many2many 表中创建的。

接下来我应该尝试什么?

标签: parsinggoyamlgo-gorm

解决方案


好吧,这就是我最终做的事情:额外的间接级别。

没有指向[]*Activity,而是添加了一个新RelatedActivity的 uuid。

// Activity
type Activity struct {
    ID                uuid.UUID         `yaml:"id" gorm:"type:uuid;primaryKey"`
    ActivityStreamID  uuid.UUID         `yaml:"stream" gorm:"type:uuid"`
    MaturityLevelID   uuid.UUID         `yaml:"level" gorm:"type:uuid"`
    Title             string            `yaml:"title"`
    Benefit           string            `yaml:"benefit"`
    ShortDescription  string            `yaml:"shortDescription"`
    LongDescription   string            `yaml:"longDescription" gorm:"type:text"`
    Results           StringArray       `yaml:"results" gorm:"type:text[]"`
    Metrics           StringArray       `yaml:"metrics" gorm:"type:text[]"`
    Costs             string            `yaml:"costs"`
    Personnel         StringArray       `yaml:"personnel" gorm:"type:text[]"`
    Notes             string            `yaml:"notes"`
    RelatedActivities []RelatedActivity `yaml:"relatedActivities" gorm:"many2many:linked_activities"`
    Type              string            `yaml:"type"`
    Questions         []Question        `gorm:"type:uuid;many2many:activity_questions;"`
}

type RelatedActivity struct {
    ID uuid.UUID `yaml:"id" gorm:"type:uuid"`
}

还实现了UnmarshalYAMLtype RelatedActivity,如下所示:

// Implements the Unmarshaler interface of the yaml pkg.
func (r *RelatedActivity) UnmarshalYAML(unmarshal func(interface{}) error) error {
    var myuuid uuid.UUID
    err := unmarshal(&myuuid)
    if err != nil {
        return err
    }

    r.ID = myuuid

    return nil
}

这在表中创建了正确的 many2many 关系linked_activities

sqlite> select * from linked_activities ;
27cdd2a3-36a4-4e56-a426-32c7a78fcf4f|e17d5735-1090-4f65-a1fe-6040b56ad0b1
1cc77725-cb23-49f3-9447-7838668f6184|e17d5735-1090-4f65-a1fe-6040b56ad0b1
93dff7be-5f95-4f8d-87d2-4f4261002508|921ff24f-0b9f-4df9-a512-9aa2f8a4a570
93dff7be-5f95-4f8d-87d2-4f4261002508|b3b20a75-740c-4880-a21a-d9aa0c1298c7
d1cb54f1-ddd3-4324-8051-3df320fc0ff8|93dff7be-5f95-4f8d-87d2-4f4261002508
2bf0e192-a904-444b-8a2f-38c33256e80a|00000000-0000-0000-0000-000000000000
15d73a64-818c-4301-9504-c8d938ca2434|2bf0e192-a904-444b-8a2f-38c33256e80a
15d73a64-818c-4301-9504-c8d938ca2434|c1aef013-7df1-400c-bdd3-c660b609b7b2
15d73a64-818c-4301-9504-c8d938ca2434|05073fb1-30c7-4143-a12a-6ba74a44c580
d955a7b3-fbfc-4b6a-a5b3-27af9e01c377|11dd0c95-f891-4b6c-b850-a27f0557a9dd
d955a7b3-fbfc-4b6a-a5b3-27af9e01c377|281369f4-91da-4d4c-84b0-729e344e2c93
d955a7b3-fbfc-4b6a-a5b3-27af9e01c377|05a3e75c-6c65-4ae5-8a11-5cbf4295662b
f2a309b8-2fbc-46cf-b2f1-1c9cde20dc0a|5bcb5237-5a0f-4085-bb12-266c9ecfa84d
f2a309b8-2fbc-46cf-b2f1-1c9cde20dc0a|4f6a0679-6d08-40de-bcc7-75ea1af65679
f2a309b8-2fbc-46cf-b2f1-1c9cde20dc0a|a395d699-17b9-47b2-8d59-95738d716283
bcc960e8-35aa-4ad5-8a9d-39a272cbf6f1|4f6a0679-6d08-40de-bcc7-75ea1af65679

我认为这应该由gorm处理,但至少它适用于我的情况。


推荐阅读