ctrlmaniac
ctrlmaniac

Reputation: 444

How to resolve a Graphql Union with Gorm?

I have a union on two concrete types Prodotto and ProdottoVariante both implements a interface of type Articolo.

union Articoli = Prodotto | ProdottoVariante

extend type Query {
  articoli: [Articoli!]!
}

I want to query all Prodotto and all ProdottoVariante by typing articoli but I don't know how to resolve Articoli

I'm trying in this way:

func (r *queryResolver) Articoli(ctx context.Context) ([]model.Articoli, error) {
    var articoli []model.Articoli

    r.DB.Model(&model.Prodotto{}).Select("nome").Find(&articoli)
    r.DB.Model(&model.ProdottoVariante{}).Select("nome").Find(&articoli)

    return articoli, nil
}

and I'm querying in this way:

query {
  articoli {
    __typename
    ...on Prodotto {
      nome
    }
  }
}

but I get this error:

{
  "errors": [
    {
      "message": "must not be null",
      "path": [
        "articoli",
        0
      ]
    }
  ],
  "data": null
}
sql: Scan error on column index 0, name "nome": unsupported Scan, storing driver.Value type string into type *model.Articoli

How to correctly resolve Unions with gorm?

Upvotes: 2

Views: 891

Answers (1)

Emin Laletovic
Emin Laletovic

Reputation: 4324

You could always try to create a join between prodotto and prodotto_variante tables and select the needed columns to populate the fields in the Articoli struct.

I'm not sure how your prodotto and prodotto_variante tables relate to each other. I'm also assuming that the nome column is part of the prodotto table and that it corresponds to a field in the Articoli struct. The code would look something like this:

func (r *queryResolver) Articoli(ctx context.Context) ([]model.Articoli, error) {
    var articoli []model.Articoli

    err:= r.DB.Table("prodottos").
               Join("JOIN prodotto_variantes pv ON prodotto.id = pv.prodotto_id").
               Find(&articoli).Error

    return articoli, err
}

The above code should populate the entire Articoli struct, if the struct fields match the columns in the prodottos table.

If you want to populate just some of the fields, you can do it in a couple of ways.

Example 1

// this should work if populating more than one field
err:= r.DB.Table("prodottos").
                   Join("JOIN prodotto_variantes pv ON prodotto.id = pv.prodotto_id").
                   Select("prodottos.id, prodottos.nome").
                   Find(&articoli).Error

Example 2

// this should work if you want to populate only one field
type Art struct {
   Nome string
}
var arts []Art
err:= r.DB.Table("prodottos").
                   Join("JOIN prodotto_variantes pv ON prodotto.id = pv.prodotto_id").
                   Find(&arts).Error

Upvotes: 1

Related Questions