2017-11-24 6 views
0

Ich möchte, welcher Ansatz klären, die ich für meine Resolver-Funktionen in Apollo + GraphQLWelches ist die richtige Resolver-Funktion?

Nehmen wir an, das folgende Schema verwendet werden soll:

wie diese
type Post { 
    id: Int 
    text: String 
    upVotes: Int 
} 

type Author{ 
    name: String 
    posts: [Post] 
} 

schema { 
    query: Author 
} 

Die ApoloGraphql tutorial schlägt eine Resolver-Karte:

{Query:{ 
    author(_, args) { 
     return author.findAll() 
      } 
    } 
}, 
Author { 
    posts: (author) => author.getPosts(), 
} 

Soweit ich weiß, jede Logik in Bezug auf Beiträge z get author with posts where the count of post upVotes > args.upVotes, muss in der author Methode behandelt werden. Das gibt uns die folgende Resolver Karte:

{Query:{ 
    author(_, args) { 
     return author.findAll({ 
       include:[model: Post] 
       where: {//post upVotes > args.upVotes} 
       }) 
      } 
}, 
Author { 
    posts: (author) => author.getPosts(), 
} 

Aufruf author, wird zuerst der Autor mit den Beiträgen wählen in einer Abfrage verbunden, wo Beiträge größer als args.upVotes. Dann wird er die Beiträge für diesen Autor wählen Sie erneut in einer weiteren Abfrage wegen Author ... getPosts()

Technisch ich das gleiche Ergebnis Author durch Entfernen erreichen kann, da Beiträge bereits im kleinen author Verfahren enthalten sind.

ich folgende Fragen:

  1. Benötige ich diese Aussage? In welchen Fällen?

    Author { posts: (author) => author.getPosts(), }

  2. Wenn nein, wie kann ich dann herausfinden, ob die Beiträge Feld angefordert wurde, so dass ich die Pfosten sind bedingt machen kann, hängt nicht nur von den Argumenten, sondern auch auf den erforderlichen Feldern ?

  3. Wenn ja, welche Beiträge enthalten das Endergebnis? Beiträge von der Include-Anweisung oder die getPosts()?

Antwort

1

Der Resolver Karte Sie in Ihrer Frage enthalten ist ungültig. Ich werde Sie so etwas wie dies für die Author Typ übernehmen soll:

Author { 
    posts: (author) => author.getPosts(), 
} 

Solange Ihre author Abfrage immer auf ein Array von Objekten löst, die eine posts Eigenschaft enthalten, dann sind Sie richtig in zu denken, dass es keinen Sinn macht, einen Kundenresolver für das Feld posts auf dem Typ Author einzuschließen. In diesem Fall füllt der Resolver Ihrer Abfrage bereits alle erforderlichen Felder, und wir müssen nichts anderes tun.

GraphQL verwendet einen Standard-Resolver, der nach Eigenschaften des übergeordneten Objekts (oder Stammobjekts) sucht, das an den Resolver übergeben wird, und verwendet diese, wenn sie mit dem Namen des aufgelösten Felds übereinstimmen. Wenn also GraphQL das Feld posts auflöst und es keinen Resolver für posts gibt, sieht es standardmäßig das Objekt Author an, mit dem es zu tun hat, und wenn es eine Eigenschaft mit dem Namen posts gibt, löst es das Feld auf seinen Wert auf .Wenn wir einen benutzerdefinierten Resolver bereitstellen, überschreibt dieser Resolver das Standardverhalten. Also, wenn Ihr Resolver war, zum Beispiel:

posts:() => [] 

dann eine leere Menge der Beiträge GraphQL würde immer wieder zurückkehren, auch wenn die zurückgegebenen Objekte von author.findAll() Beiträge enthalten.

Wann müssten Sie den Resolver für posts einbeziehen?

Wenn Ihr author Resolver die Posts nicht "einschloss", aber der Client dieses Feld anforderte. Wie Sie bereits gesagt haben, besteht das Problem darin, dass wir möglicherweise in einigen Fällen einen unnötigen zusätzlichen Anruf tätigen, je nachdem, ob Ihr Resolver author die Posts "einbezieht" oder nicht. Sie können rund um das erhalten, indem so etwas wie dies zu tun:

posts: (author) => { 
    if (author.posts) return author.posts 
    return author.getPosts() 
} 
// or more succinctly 
posts: author => author.posts ? author.posts : author.getPosts() 

diese Weise nennen wir nur getPosts wenn wir tatsächlich die Beiträge erhalten müssen. Alternativ können Sie den posts Resolver weglassen und diesen in Ihrem author Resolver behandeln. Wir können uns das vierte Argument ansehen, das an den Resolver übergeben wurde, um Informationen über die Anfrage zu erhalten, einschließlich der angeforderten Felder. Zum Beispiel Ihr Resolver wie folgt aussehen könnte:

author: (root, args, context, info) => { 
    const include = [] 
    const requestedPosts = info.fieldNodes[0].selectionSet.selections.includes(s => s.name.value === 'posts' 
    if (requestedPosts) include.push(Post) 
    return Author.findAll({include}) 
} 

Jetzt Ihr Resolver enthält nur die Einträge für jeden Autor, wenn der Kunde ausdrücklich darauf angefordert. Das AST-Tree-Objekt, das dem Resolver zur Verfügung gestellt wird, ist unordentlich zu analysieren, aber es gibt Bibliotheken da draußen (wie this one), um damit zu helfen.

+0

Vielen Dank, sehr gute Antwort. Der Typ "Autor" war in der Tat falsch. – henk

Verwandte Themen