點燈坊

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

使用 Apollo GraphQL 建立 Mutation

Sam Xiao's Avatar 2019-11-04

GraphQL 除了使用 Query 查詢資料外,若要異動資料,包含新增、修改、刪除,都要使用 Mutation。

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 },
  { title: 'RxJS in Action', price: 200 }
]

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

  type Mutation {
    addBook(book: BookInput!): Book
  }

  type Book {
    title: String
    price: Int
  }

  input BookInput {
    title: String
    price: Int
  }
`

let books = () => data

let addBook = (_, { book }) => {
  data = [...data, book]
  return book;
}

let resolvers = {
  Query: { books },
  Mutation: { addBook }
}

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

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

第 9 行

type Query {
  books: [Book]
}

Query 下宣告 books query 回傳所有 Book type 資料。

17 行

type Book {
  title: String
  price: Int
}

宣告 Book type。

13 行

type Mutation {
  addBook(book: BookInput!): Book
}

Mutation 下宣告 addBook mutation 新增 book。

Mutation 雖然也能直接使用內建的 scalar type,如 String、Int,但因為 mutation 通常會新增大量資料,為避免 argument 太長,通常會搭配 Input 自訂 type。

22 行

input BookInput {
  title: String
  price: Int
}

使用 input 宣告 BookInput input type,GraphQL 規定 input 命名須以 Input 為 postfix。

28 行

let books = () => data

books query 直接回傳所有資料。

30 行

let addBook = (_, { book }) => {
  data = [...data, book]
  return book;
}

Apollo GraphQL 的 resolver 依序有 4 個 argument: parentargscontextinfo,讀取 argument 只會用到第二個 args,而 parent 目前用不到可用 _ 表示, contextinfo 目前可忽略。

args 直接 destructure book,產生新的 id 直接新增至 id property。

book object 新增至 data 並回傳。

GraphQL Playground

query {
  books {
    title
    price
  }
}

使用 books query,回傳其 titleprice 兩個 property,共 2 筆資料。

mutation002

mutation {
  addBook(book: {
    title: "Speaking JavaScript"
    price: 300
  }) {
    title
    price
  }
}

使用 adeBook() mutation,傳入 book variable 為 argument。

mutation003

回傳 book object,重點是包含了剛新增的 id property。

query {
  books {
    title
    price
  }
}

再次執行 query,會發現資料已經新增成功。

mutation004

Conclusion

  • Apollo GraphQL 的 query 與 mutation 寫法類似,唯 query 可直接使用 scalar type 與自訂 type;而 mutation 需使用自訂 input type

Reference

Eve Porcello, Use an Input Type to Create an Account with a GraphQL Mutation