有没有一种方法可以支持Go中GraphQL和Mongo的多态属性?

时间:2020-07-04 13:26:17

标签: mongodb go graphql polymorphism

我正在开发一个Go应用程序,该应用程序利用gqlgen(GraphQL代码生成器)与客户端进行通信,并使用MongoDB作为后端数据库。对于我们的GraphQL模式,我们有几种类型的游戏(GameAGameBGameC等),都实现了基本的Game类型。客户端请求游戏大厅(具有Game属性),并作为整体从查询中获得当前正在玩的任何游戏作为回报。 gqlgen将此模式转换为具有单个必需功能的Game接口:IsGame(),用于将各种类型的游戏与单个接口相关联。

//models.go

/* ... */

// Define the Game interface
type Game interface {
    IsGame()
}

// Define GameA 
type GameA struct {
    ID      primitive.ObjectID `json:"id" bson:"_id"`
    Score   []int              `json:"score"`
    Players []Player           `json:"players"`
}

// GameA implements the Game interface
func (g GameA) IsGame() {}

/* ... */

以上代码在GraphQL服务器和客户端通信之前一直有效。 尝试向Mongo读写Game时出现问题,因为我们无法提前知道游戏的类型:

//db.go

/* ... */

// SetGame takes a game model, game ID, and an insert switch to update a game in the db.
// If insert is true and a game with a matching ID does not already exist, a new
// game will be created.
func (c *Client) SetGame(game *models.Game, id primitive.ObjectID, insert bool) error {
    d, err := bson.Marshal(game)
    if err != nil {
        return err
    }

    res, err := c.GameCollection.ReplaceOne(
        context.TODO(), bson.M{"_id": id}, d,
        options.Replace().SetUpsert(insert),
    )
    if err != nil {
        return err
    }

    if res.UpsertedCount == 0 && res.MatchedCount == 0 {
        return fmt.Errorf("no games with ID %s found.", id.Hex())
    }
    return nil
}


// GetGame accepts an ID (primitive.ObjectID) and
// returns the game it discovers.
func (c *Client) GetGame(id primitive.ObjectID) (*models.Game, error) {
    var result *models.Game // This doesn't work obviously, since we don't know what type of game it is

    err := c.GameCollection.FindOne(
        context.TODO(), bson.M{"_id": id},
    ).Decode(&result)
    return result, err
}

/* ... */

从理论上讲,SetGame(...)应该可以按预期工作,但是GetGame(...)不能这样做,因为.Decode()需要一种将结果清空的结构。如果不提前知道游戏类型,就无法正确解码FindOne(...)函数的结果。这把我引到我的问题:

为每种类型的游戏制作多个GetGameX(...)函数(此函数会随着时间的推移而增加,因此尝试减少编码开销)是很短的,有没有办法使这些函数支持多态还是没有GraphQL和Mongo的属性?

如果没有,是否有不需要更好的解决方案而无需编写大量不必要的“重复”代码?

0 个答案:

没有答案