mickhansen / graphql-sequelize

GraphQL & Relay for MySQL & Postgres via Sequelize
MIT License
1.9k stars 172 forks source link

Combining multiple associations #694

Closed cskiwi closed 4 years ago

cskiwi commented 4 years ago

Hi,

For the project I'm working on a player has multiple games. But these are always needed in a combined way. So I was wondering how I could make a schema that allows this.

@Table({
  timestamps: true
})
export class Player extends Model<Player> {

  @Column({ unique: 'compositeIndex' })
  firstName: string;

  @Column({ unique: 'compositeIndex' })
  lastName: string;

  @Column({ unique: 'compositeIndex' })
  memberId: string;

  // Assicioations
  @HasMany(() => Game, { as: 'player1-team1', foreignKey: 'player1Team1Id' })
  games1?: Game[];
  @HasMany(() => Game, { as: 'player1-team2', foreignKey: 'player1Team2Id' })
  games2?: Game[];
  @HasMany(() => Game, { as: 'player2-team1', foreignKey: 'player2Team1Id' })
  games3?: Game[];
  @HasMany(() => Game, { as: 'player2-team2', foreignKey: 'player2Team2Id' })
  games4?: Game[];

  @Column(DataType.VIRTUAL(DataType.STRING, ['firstName', 'lastName']))
  get fullName(this: Player): string {
    return `${this.firstName || ''} ${this.lastName || ''}`.trim();
  }

  get games() {
    return [...this.games1, ...this.games2, ...this.games3, ...this.games4];
  }
}

Current Scheme object


  const playerType = new GraphQLObjectType({
    name: 'Player',
    description: 'A Player',
    fields: Object.assign(attributeFields(sequelizeInstance.models.Player), {
      games: {
        type: new GraphQLList(gameType),
        resolve: resolver(/* Some magic here? */),
//     resolve: resolver(Player.associations['player1-team1'])  // this works for the player's games as player 1 in team 1
      }
    })
  });

  return new GraphQLSchema({
    query: new GraphQLObjectType({
      name: 'RootQueryType',
      fields: {
        player: {
          type: playerType,
          args: {
            id: {
              description: 'id of the user',
              type: new GraphQLNonNull(GraphQLID)
            }
          },
          resolve: resolver(Player)
        }
      }
    })
  });
};

Than a secondary question: I would need the same for like the fullName. is this done the same? UPDATE: found out how to do the name (see virtual part)

cskiwi commented 4 years ago

Found a 'solution' to my problem I've made the "error" that I've made 4 foreign keys. by creating a many to many releation i was able to get everything working as I wanted to.

But I'm still curious on how one would do this ...

mickhansen commented 4 years ago

@cskiwi Do what exactly? Update your code to show your N:M relation in the resolver

cskiwi commented 4 years ago

@cskiwi Do what exactly? Update your code to show your N:M relation in the resolver

Combine multiple linked models as one (in my case I wan't to combine the values of games1, games2, games3, games4 and threat them as a single HasMany in graphql).

I don't know what to add. the only thing I could add in the resolver is the following, but this is the thing I don't want:

 const playerType = new GraphQLObjectType({
    name: 'Player',
    description: 'A Player',
    fields: Object.assign(attributeFields(sequelizeInstance.models.Player), {
      games: {
        type: new GraphQLList(gameType),
        resolve: resolver(/* Some magic here? */),
//     resolve: resolver(Player.associations['player1-team1'])  // this works for the player's games as player 1 in team 1
      },
      games1: {
        type: new GraphQLList(gameType),
        resolve: resolver(Player.associations['player1-team1'])
      },
      games2: {
        type: new GraphQLList(gameType),
        resolve: resolver(Player.associations['player2-team1'])
      },
      // ...
    })
  });
mickhansen commented 4 years ago

@cskiwi Ah i see. Unless you can express it in a single association you'll need to write a resolver.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.