點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Apollo GraphQL 建立 Nested Query

Sam Xiao's Avatar 2019-10-19

JSON 天生就有 Nested Object,而 GraphQL 亦提供 Nested Query,且非常優雅。

Version

macOS Catalina 10.15
WebStorm 2019.2.3
Node 10.16.3
Apollo GraphQL 2.9.6

Apollo GraphQL

src/index.js

import { apolloServer, gql } from 'apollo-server'

let data = [
  {
    title: 'FP in JavaScript',
    price: 100,
    photo: {
      full: 'fpjs-full.png',
      thumb: 'fpjs-small.png'
    }
  },
  {
    title: 'RxJS in Action',
    price: 200,
    photo: {
      full: 'rxjs-full.png',
      thumb: 'rxjs-small.png'
    }
  },
  {
    title: 'Speaking JavaScript',
    price: 300,
    photo: {
      full: 'spjs-full.png',
      thumb: 'spjs-small.png'
    }
  }
]

let typeDefs = gql`
  type Query {
    books: [Book]
  }

  type Book {
    title: String
    price: Int
    photo: Photo
  }

  type Photo {
    full: String
    thumb: String
  }
`;

let books = () => data

let resolvers = {
  Query: {
    books
  }
};

let apolloServer = new ApolloServer({ typeDefs, resolvers })

apolloServer.listen()
  .then(({ url }) => `GraphQL Server ready at ${ url }`)
  .then(console.log)

第 3 行

let data = [
  {
    title: 'FP in JavaScript',
    price: 100,
    photo: {
      full: 'fpjs-full.png',
      thumb: 'fpjs-small.png'
    }
  },
  {
    title: 'RxJS in Action',
    price: 200,
    photo: {
      full: 'rxjs-full.png',
      thumb: 'rxjs-small.png'
    }
  },
  {
    title: 'Speaking JavaScript',
    price: 300,
    photo: {
      full: 'spjs-full.png',
      thumb: 'spjs-small.png'
    }
  }
]

除了 titleprice 外,還多了 photo,且 data 本身就是 nested object。

41 行

type Photo {
  full: String
  thumb: String
}

其中 photo 為 object,因此需要新的 Photo type。

47 行

let books = () => data

在 resolver 定義 books() query 實作。

GraphQL Playground

query {
  books {
    title
    photo {
      full
    }
  }  
}

使用 books query,只回傳 titlephoto,由於 photo 為 object,又可再指定只要 full property,此為 nested GraphQL query。

nested000

Conclusion

  • 原本看似複雜的 nested query,可是 GraphQL 寫起來卻十分優雅

Reference

Eve Porcello, Send a Nested GraphQL Query