クライアント側からソートのデータを渡してもらうことによって、バックエンドではそれを元にしてデータを渡すだけの状況を作りたいと思います。
// schema.ts
export const UserObject = objectType({
name: 'User',
definition(t) {
t.string('name')
t.string('email')
t.string('role')
}
})
export const UserQuery = extendType({
type: 'Query',
definition(t) {
t.list.field('users', {
type: UserObject,
args: {
orderBy: /*...*/,
},
async resolve(_root, args, { prisma }) {
// これがやりたい
//[{ name: 'desc' }, { role: 'asc' }]
console.log(args.orderBy)
return prisma.user.findMany({
orderBy: args.orderBy
})
},
})
},
})
ちょっと見にくいですが、args.orderByに[{ name: 'desc' }, { role: 'asc' }]
を渡したいという感じです。
enumTypeとinputObjectTypeを使って定義する
enumType
でvalueに'desc' | 'asc'
のみを許可するようにします。
inputはinputObjectType
で定義することでNexusの方で生成してくれます。
このOrderBy
の定義はnullを許容しているのでどちらもプロパティもなくても問題ありません。
export const OrderByMembers = enumType({
name: 'OrderByMembers',
members: ['desc', 'asc'],
})
export const OrderByType = inputObjectType({
name: 'OrderByType',
definition(t) {
t.field('name', {
type: OrderByMembers
})
t.field('role', {
type: OrderByMembers
})
}
})
これを配列で渡せるようにしていきます。
export const UserQuery = extendType({
type: 'Query',
definition(t) {
t.list.field('users', {
type: UserObject,
args: {
// inputObjectTypeで定義したものをlist()で追加
orderBy: list('OrderBy'),
},
async resolve(_root, args, { prisma }) {
console.log(args.orderBy)
return prisma.user.findMany({
orderBy: args.orderBy
})
},
})
},
})
クライアントのQueryについて
クライアントはApollo Clientを使用しています。
生成されたschemaを見るとinput OrderBy { ... }
があると思うので、配列で投げれるように[OrderBy]
を記述します。
自分はTypeScriptの要領でOrderBy[]
と書いてハマってました。
import { gql, useQuery } from '@apollo/client'
const QUERY = gql`
query($orderBy: [OrderBy]) {
users(orderBy: $orderBy) {
name
email
role
}
}
`
const { data } = useQuery<{ users: User[] }>(QUERY, {
variables: {
orderBy: [{ name: 'desc' }]
}
})
今回はシンプルなorderByを想定しましたが、実際は{ members: { posts: { count: 'desc' } } }
みたいな記述も出てくるので、少し悩んでいます。
ソートや絞り込みなどクライアントからパラメーターを渡して使用する頻度は多いと思うけど、Nexusの定義方法についての詳細な記述は少なかったです。(各々ドキュメントに書いてあって組み合わせるだけだから理解できるよねって感じだとは思います。)