2017-11-01 33 views
6

Nowym aby graphQL używam następujący schemat:Scalanie 2 punktów końcowych REST do jednej odpowiedzi GraphQL

type Item { 
    id: String, 
    valueA: Float, 
    valueB: Float 
    } 

    type Query { 
    items(ids: [String]!): [Item] 
    } 

Moje API może zwracać wiele elementów na jednym żądanie każdego typu (A & B), ale nie dla obu, tj:

REST Zapytanie o TypeA: api/a/items?id=[1,2]
Response:

[ 
    {"id":1,"value":100}, 
    {"id":2,"value":30} 
] 

REST Wniosek o t ypeB: api/b/items?id=[1,2]
Response:

[ 
    {"id":1,"value":50}, 
    {"id":2,"value":20} 
] 

chciałbym połączyć te 2 punkty końcowe api w jednym graphQL Response tak:

[ 
    { 
    id: "1", 
    valueA: 100, 
    valueB: 50 
    }, 
    { 
    id: "2", 
    valueA: 30, 
    valueB: 20 
    } 
] 

Q: Jak można by napisać resolver, który uruchomi pobieranie pojedynczego dla każdego typu (uzyskiwanie odpowiedzi wielu elementów), upewniając się, że niepotrzebne pobieranie nie jest wyzwalane, gdy zapytanie jest brakuje tj typ:

{items(ids:["1","2"]) { 
    id 
    valueA 
}} 

Powyższy przykład powinien jedynie sprowadzić api/a/items?id=[1,2] a odpowiedź graphQL powinno być:

[ 
    { 
    id: "1", 
    valueA: 100 
    }, 
    { 
    id: "2", 
    valueA: 30 
    } 
] 

Odpowiedz

2

więc założyć używasz JavaScript jako język. Co trzeba w tym przypadku nie jest w użyciu bezpośredni zapytanie, raczej wykorzystywać fragmenty

Więc zapytania staną

{ 
    items(ids:["1","2"]) { 
     ...data 
    }} 

    fragment data on Item { 
     id 
     valueA 
    } 
} 

Następny w rezolwerem musimy uzyskać dostęp do tych fragmentów znaleźć pola, które są częścią fragment, a następnie rozwiązuj dane w oparciu o to samo. Poniżej znajduje się prosty plik nodejs z samym

const util = require('util'); 

var { graphql, buildSchema } = require('graphql'); 

var schema = buildSchema(` 
    type Item { 
     id: String, 
     valueA: Float, 
     valueB: Float 
    } 

    type Query { 
     items(ids: [String]!): [Item] 
    } 
`); 

var root = { items: (source, args, root) => { 
     var fields = root.fragments.data.selectionSet.selections.map(f => f.name.value); 
     var ids = source["ids"]; 

     var data = ids.map(id => {return {id: id}}); 
     if (fields.indexOf("valueA") != -1) 
     { 
      // Query api/a/items?id=[ids] 
      //append to data; 
      console.log("calling API A") 
      data[0]["valueA"] = 0.12; 
      data[1]["valueA"] = 0.15; 
     } 

     if (fields.indexOf("valueB") != -1) 
     { 
      // Query api/b/items?id=[ids] 
      //append to data; 
      console.log("calling API B") 
      data[0]["valueB"] = 0.10; 
      data[1]["valueB"] = 0.11; 
     } 
     return data 
}, 
}; 

graphql(schema, `{items(ids:["1","2"]) { 
     ...data 
    }} 

    fragment data on Item { 
     id 
     valueA 
    } 

    `, root).then((response) => { 
    console.log(util.inspect(response, {showHidden: false, depth: null})); 
}); 

Gdybyśmy go uruchomić, wyjście jest

calling API A 
{ data: 
    { items: [ { id: '1', valueA: 0.12 }, { id: '2', valueA: 0.15 } ] } } 

Jeśli mamy zmienić zapytanie do

{ 
    items(ids:["1","2"]) { 
     ...data 
    }} 

    fragment data on Item { 
     id 
     valueA 
     valueB 
    } 
} 

Wyjście jest

calling API A 
calling API B 
{ data: 
    { items: 
     [ { id: '1', valueA: 0.12, valueB: 0.1 }, 
     { id: '2', valueA: 0.15, valueB: 0.11 } ] } } 

To pokazuje, w jaki sposób można oid wywołanie api A/B, gdy ich pola nie są potrzebne. Dokładnie tak, jak prosiłeś o

+0

Działa jak czar :) –

Powiązane problemy