Search code examples
graphqlprisma-graphqltypegraphql

graphql prisma query get artists who has song track


I have three table, artist, album and track. I want to query artist who have at least one song track.

Here is my graphql prisma schema. May I know how write the query?

generator client {
  provider = "prisma-client-js"
  binaryTargets = ["native", "linux-musl"]
}

generator typegraphql {
   provider           = "typegraphql-prisma"
  emitTranspiledCode = true
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model Artist {
  id              String    @id @default(cuid())
  name            String    @unique @db.VarChar(255)
  bio             String?   @db.VarChar(1024)
  profile_picture String    @db.VarChar(512)
  albums          Album[]
  tracks          Track[]
  active          Boolean   @default(true)
  user            User      @relation(fields: [user_id], references: [id])
  user_id         String
  created_at      DateTime  @default(now())
  updated_at      DateTime? @updatedAt

  @@map("artists")
}

model Album {
  id          String    @id @default(cuid())
  title       String    @db.VarChar(255)
  album_cover String    @db.VarChar(512)
  description String?   @db.VarChar(5120)
  released    Int       @default(1900)
  artists     Artist[]
  genres      Genre[]
  tracks      Track[]
  active      Boolean   @default(true)
  user        User      @relation(fields: [user_id], references: [id])
  user_id     String
  created_at  DateTime  @default(now())
  updated_at  DateTime? @updatedAt

  @@map("albums")
}

model Track {
  id          String       @id @default(cuid())
  title       String       @db.VarChar(255)
  description String?      @db.VarChar(5120)
  lyric     String?      @db.LongText
  mp3_url     String       @db.VarChar(1024)
  youtube_url String       @db.VarChar(1024)
  band       String?      @db.VarChar(255)
  duration    Int          @default(0)
  artists     Artist[]
  album       Album        @relation(fields: [album_id], references: [id])
  album_id    String
  songWriters SongWriter[]
  active      Boolean      @default(true)
  user        User         @relation(fields: [user_id], references: [id])
  user_id     String
  created_at  DateTime     @default(now())
  updated_at  DateTime?    @updatedAt

  @@map("tracks")
}

Here is Resolver

import { Resolver, ArgsType, Field, Args, Query, Ctx, ObjectType, 
Int } from "type-graphql";
import { Artist } from "@generated/type-graphql";
import { Context } from "../interfaces";

@ArgsType()
export class ArtistArgs {
  @Field((type) => Int, { nullable: false })
  page!: number;

  @Field((type) => Int, { nullable: false })
  take!: number;
}

@ObjectType()
export class ArtistResponse {
  @Field(type => [Artist])
  artists: Artist[] =[];
  @Field((type) => Int, { nullable: false })
  total!: number;
}


@Resolver()
class ArtistResolver {

  //@Authorized("ADMIN")
  @Query((returns) => ArtistResponse, { nullable: true })
  async getArtists(@Ctx() { req, res, prisma }: Context, @Args() 
  { page, take }: ArtistArgs): Promise<ArtistResponse | null> {
    const artists = (await prisma.artist.findMany({
      take: take,
      skip: (page - 1) * take,
      orderBy: [
        {
          name: "asc"
        }
      ]
    }));

    const count = (await prisma.artist.count({

    }));
    return {artists: artists, total: count};
  }
}


export default ArtistResolver;

Solution

  • This is like my answer in Prisma js ORM - how to filter for results that have entry in a related table (effectively JOIN)?

    To get only Artists that have at least one Track, you should use some and specify a condition that always return true for any related record that exists.

    And if you want to your query includes related Tracks you must specify it in include property.

     await prisma.artist.findMany({
       where: {
         tracks: {
           some: {
             id: { not: "" } // It always should be true.
           },
         },
       },
       
       // if you want to include related tracks in returned object:
       include: {
         tracks: true,
       },
     });