theme | layout | highlighter | lineNumbers | info | drawings | background | download | |
---|---|---|---|---|---|---|---|---|
apple-basic |
intro |
shiki |
true |
## Slidev Starter Template
Dataloadery | Co to je? K čemu to používat?
Learn more at [Sli.dev](https://sli.dev)
|
|
true |
Dmitrij Tkačenko | 8.12.2021
- dotahujeme relace na základě contextu nadřazeného resolveru
- relace se starají samy o sebe
- strom skládáme postupně
- lazy loading
- nejen na relace - dobré i třeba na deprecated fields, nebo jednoduché fieldy s nějakou logikou
@ObjectType()
class Recipe {
@Field()
title: string;
@Field({ deprecationReason: "Use `title` instead" })
get name(): string {
return this.title;
}
}
👉 VSCode
InvoiceResolver...
@Query(() => PaginatedInvoiceResponse)
async invoices(@Args() invoicesArgs: InvoicesArgs, @Ctx() { container }: GraphqlContext): Promise<PaginatedInvoiceResponse> {
const { items, total } = await container.invoiceService.getAllInvoices(invoicesArgs)
return {
items: items.map((i) => mapInvoiceEntityToObjectType(i)),
total,
}
}
@Query(() => InvoiceResponse)
async invoice(@Args() { id }: InvoiceArgs, @Ctx() { container }: GraphqlContext): Promise<InvoiceResponse | null> {
const invoice = await container.invoiceRepository.findOne({ where: { id }, relations: ['rewards', 'pickupPoint'] })
if (!invoice) {
throw new BaseApolloError(new InvoiceNotFound(`The invoice with the id of: "${id}" was not found!`, id))
}
return mapInvoiceEntityToObjectType(invoice)
}
- a rozdíl dotazování do DB
- za mě ano
- menší chybovost
- větší přehlednost
- jednoduše se můžeme zbavit nadbytečných dotazů do DB
Diskuze 🗣
"DataLoader is a generic utility to be used as part of your application's data fetching layer to provide a simplified and consistent API over various remote data sources such as databases or web services via batching and caching."
@Fb, @leebyron
Stažení týdně
Získat unifikované API pro získávání dat z různých nezávislých zdrojů. Zároveň mít vyřešenou optimalizaci.
- dotahuji seznam stejných typů hodnot ze stejné DB v různých částech dotazu
- do vstupu pošlu seznam klíčů (typicky IDs)
- na výstupu Promise se seznamem odpovídajících hodnot
- dotahuji stejnou hodnotu z DB jednou
- identifikace podle klíče
- cache per request
obě techniky se navzájem kombinují
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
name: { type: GraphQLString },
bestFriend: {
type: UserType,
resolve: user => userLoader.load(user.bestFriendID)
},
friends: {
args: {
first: { type: GraphQLInt }
},
type: new GraphQLList(UserType),
resolve: async (user, { first }) => {
const rows = await queryLoader.load([
'SELECT toID FROM friends WHERE fromID=? LIMIT ?', user.id, first
])
return rows.map(row => userLoader.load(row.toID))
}
}
})
})
- bez Dataloaderu až 13 DB dotazů
- s Dataloadery max 4
👉 VSCode
@FieldResolver()
async pickupPoint(@Root() invoice: Invoice, @Ctx() { container }: GraphqlContext): Promise<PickupPointResponse | null> {
if (!invoice.pickupPointPudoId) {
return null
}
const pp = await container.pickupPointRepository.findOneOrFail({
where: {
pudoId: invoice.pickupPointPudoId,
},
})
return mapPickupPointEntityToObjectType(pp)
}
// VS
@FieldResolver()
async pickupPoint(@Root() invoice: Invoice, @Ctx() { loaders }: GraphqlContext): Promise<PickupPointResponse | null> {
if (!invoice.pickupPointPudoId) {
return null
}
const pp = await loaders.pickupPointByPudo.load(invoice.pickupPointPudoId)
return mapPickupPointEntityToObjectType(pp)
}
- za mě v daný moment nemusíme
- nemáme zatím více datových zdrojů
- z FE nejsou moc hluboké dotazy "zatím"
- pokud budem dodržovat field resolvery, tak se dá jednoduše a postupně doimplementovat
- hybrid mod? Nechat to na pocitu, popřípadě na potřebách z FE
Diskuze 🗣
Díky 🙏
*Pro stažení PDF klikněte na v dolní liště.