javascript - Kuinka suunnitella seuraava resolver GraphQL-palvelimelle?
Käytän react-apolloa Meteorissa MySQL:n ja Sequelize:n kanssa, olen edelleen aloittelija JS:ssä. Oletetaan, että minulla on seuraava resolver-funktio apollo-serverissäni:
export default resolvers = {
Query: {
posts(_, args){
return Post.findAndCountAll({ where: args });
},
numberOfPosts(){
return /// the number of selected posts
}
}
Haluaisin valita tietokannasta joitakin tietoja, joissa tietyt ehdot täyttyvät, ja sitten laskea valittujen rivien määrän ja palauttaa ne kentässä "numberOfPosts". findAndCountAll() palauttaa objektin, joka sisältää valitut rivit ja lukumäärän. Haluaisin saada post():n palauttamaan vain valitut rivit ja numberOfPosts():n palauttamaan vain valittujen viestien lukumäärän. Tällä hetkellä molemmat palautetaan posts():in kautta.
Minun kaavioni on:
type Post {
id: Int
date: Float
text: String
}
type NumberOfPosts{
total: Int
filtered: Int
}
type Query {
posts(
id: Ind,
offset: Int,
limit: Int,
filter: String): [Post]
numberOfPosts:[NumberOfPosts]
}
schema {
query: Query
}
Tavoitteena on vastaanottaa dataa seuraavassa muodossa:
{
"data": {
"numberOfPosts": [
{
"total": 1000,
"filtered": 21
}
],
"posts": [
{
"id": 4,
"date": 5105626122,
"text": "jzybiwutudi"
},
...
]
}
}
Työni tähän mennessä: Yritys 1:
let selectedCount;
export default resolvers = {
Query: {
posts(_, args){
return Post.findAndCountAll({where: args}).then(
function (results) {
selectedCount = results.count;
return results.rows
});
},
numberOfPosts(){
return selectedCount
}
}}
Joten määritän apumuuttujan ratkaisijoiden ulkopuolella ja asetän sen valittujen rivien määräksi, sitten laskenta palautetaan numberOfPosts():ssa, mikä toimii, mutta ongelma tässä on, että return results.rows aiheuttaa virheen, enkä ymmärrä miksi.
toinen ongelma on, että selectedCount on aina edellinen rivien määrä
Yritä 2
Toinen ratkaisu, joka näyttää toimivan, on välittää argumentit GraphQL-kyselyyn kahdesti, näin:
{
numberOfPosts(filter: "example") {
total
filtered
}
posts(filter: "example") {
id
date
text
}
}
Sitten molemmat resolver-funktiot tietävät samat argumentit, joten voin valita ja laskea samat viestit. Mutta tämä ei tunnu oikealta minusta, koska minun on annettava samat argumentit kahdesti, ne myös välitetään kahdesti...
Vastaus #1
Sinun pitäisi miettiä enemmän suunnittelua ja mitä kunkin näistä kyselyistä pitäisi tehdä. Näiden kyselyiden ei pitäisi muuttaa tietokantaa tai globaalia tilaa.
Paras asia, jonka voit tehdä, on yksinkertaisesti määrittää uusi tyyppi, joka sisältää total ja filtered, kuten teit NumberOfPosts:nä ensimmäisellä yritykselläsi, ja myös viestien listan.
Joten, kaaviosi olisi tällainen:
type Post {
id: Int
date: Float
text: String
}
type PostList {
total: Int
filtered: Int
posts: [Post]
}
type Query {
posts(
id: Ind,
offset: Int,
limit: Int,
filter: String): PostList
}
schema {
query: Query
}
Ja ratkaiset posts näin:
posts(_, args) {
return Post.findAndCountAll({ where: args }).then(result => {
return {
total: 1000,
filtered: result.count,
posts: result.rows
}
})
}
Huomaa, miten laitoin juuri 1000 kokonaisluvuksi. Et voi saada rivien kokonaismäärää findAndCountAll-metodilla. Jos tarvitset sitä, voit suorittaa kaksi eri kyselyä rinnakkain ja käyttää Promise.all-metodia odottamaan niiden valmistumista.
posts(_, args) {
return Promise.all([
Post.count(),
Post.findAndCountAll({ where: args })
]).then(data => {
return {
total: data[0],
filtered: data[1].count,
posts: data[1].rows
}
})
}
Yllä oleva koodi voisi myös hyötyä ES6:n hajauttamisesta:
posts(_, args) {
return Promise.all([
Post.count(),
Post.findAndCountAll({ where: args })
]).then(([totalCount, filteredData]) => {
return {
total: totalCount,
filtered: filteredData.count,
posts: filteredData.rows
}
})
}
Nyt voit suorittaa:
query {
posts(filter:"example") {
total
filtered
posts {
id
date
text
}
}
}
ja saat:
{
"data": {
"posts": {
"total": 1000,
"filtered": 21,
"posts": [
{
"id": 4,
"date": 5105626122,
"text": "jzybiwutudi"
},
...
]
}
}
}
