前回は、特定の条件に合致したデータを抽出しました。

今回は、データを追加、削除、更新します。

GraphQL では、データを追加したり、削除、更新したりすることをミューテーションと言います。

コードは、前回のコードを使用します。

データを追加する

まずは、本のデータを追加します。

schema.js のdypeDefs内に、ミューテーションの方を作ります。

type Mutation {}

本を追加するミューテーションを作りたいので、名前をaddBookとします。

type Mutation {
  addBook
}

addBookBookを返す様にします。

type Mutation {
  addBook: Book!
}

addBookの内容をinputで設定します。

設定内容は、bookのデータにします。

input AddBookInput {
  id: Int!
  title: String!
  author: String!
  categoryId: String!
  isRead: Boolean!
}

addBookの中にAddBookInputを指定します。

type Mutation {
  addBook(input: AddBookInput!): Book!
}

スキーマが完成したので、次はリゾルバーを作成します。

resolvers フォルダの中に、Mutation.js を作成します。

Mutationをエクスポートする様にします。

exports.Mutation = {}

スキーマで設定した、addBookを追加します。

第二引数にinput、第三引数にbooksを指定します。

exports.Mutation = {
  addBook: (parent, { input }, { books }) => {},
}

input から、『id』『title』『author』『categoryId』『isRead』を指定します。

また、newBookを作成します。

inputの内容を、newBookに記述します。

exports.Mutation = {
  addBook: (parent, { input }, { books }) => {
    const { id, title, author, categoryId, isRead } = input
    const newBook = {
      id,
      title,
      author,
      categoryId,
      isRead,
    }
  },
}

newBookbooksデータに追加します。

newBooksを返します。

exports.Mutation = {
  addBook: (parent, { input }, { books }) => {
    const { id, title, author, categoryId, isRead } = input
    const newBook = {
      id,
      title,
      author,
      categoryId,
      isRead,
    }

    books.push(newBook)

    return newBook
  },
}

リゾルバーが完成したので、index.js のサーバー内にMutationを追加します。

const server = new ApolloServer({
  typeDefs,
  resolvers: {
    Query,
    Mutation,
    Category,
    Book,
  },
  context: {
    books,
    categories,
  },
})

今のところ、全ての books データを取得すると、エラーになります。

全てのデータを取得できるように、resolvers の Query.js で、id の指定がある場合のみ、filter を使う様にします。

books: (parent, { filter }, { db }) => {
  let filteredBooks = db.books;
  if (filter) {
    if (filter.isRead === true) {
      filteredBooks = filteredBooks.filter((book) => {
        return book.isRead;
      });
    }
  }

  return filteredBooks;
},

image2

books データの一覧が取得できました。

では、データが追加できるか、ブラウザで確認してみます。

GraphQL でデータを抽出するときは、queryを使いました。

今回は、mutationを使います。

mutation AddBook($input: AddBookInput!) {
  addBook(input: $input) {
    id
    title
    author
  }
}

image3

variables に追加のデータを指定します。

image4

AddBook ボタンをクリックすると、

image5

データが追加されました。

books データ一覧を取得でして、追加されているか確認してみましょう。

image6

無事、データが追加されました。

データを削除する

次は、books データを削除します。

ここで作成したデータでは、GraphQL で削除が反映されないので、データをオブジェクト内で設定する様にします。

index.js のbookscategoriesdbでまとめます。

const db = { books, categories }

context内もdbへ修正します。

const server = new ApolloServer({
  typeDefs,
  resolvers: {
    Query,
    Mutation,
    Category,
    Book,
  },
  context: {
    db,
  },
})

contextの部分を、全てdbに置き換えましょう。

resolvers/Query.js

exports.Query = {
  books: (parent, { filter }, { db }) => {
    let filteredBooks = db.books
    if (filter) {
      if (filter.isRead === true) {
        filteredBooks = filteredBooks.filter(book => {
          return book.isRead
        })
      }
    }

    return filteredBooks
  },
  book: (parent, { id }, { db }) => {
    const book = db.books.find(book => book.id === id)
    if (!book) return null
    return book
  },
  categories: (parent, args, { db }) => db.categories,
  category: (parent, { id }, { db }) => {
    const category = db.categories.find(category => category.id === id)
    if (!category) return null
    return category
  },
}

resolvers/Category.js

exports.Category = {
  books: ({ id }, args, { db }) => {
    return db.books.filter(book => book.categoryId === id)
  },
}

resolvers/Book.js

exports.Book = {
  category: ({ categoryId }, args, { db }) => {
    return db.categories.find(category => category.id === categoryId)
  },
}

resolvers/Mutation.js

exports.Mutation = {
  addBook: (parent, { input }, { db }) => {
    const { id, title, author, categoryId, isRead } = input
    const newBook = {
      id,
      title,
      author,
      categoryId,
      isRead,
    }

    db.books.push(newBook)

    return newBook
  },
}

一度、ブラウザで確認します。

image7

image8

うまく機能しています。

schema.js のMutationdeleteBookを作成します。

指定はidを指定し、成功したかどうかを知りたいので、Booleanを返す様にします。

type Mutation {
  addBook(input: AddBookInput!): Book!
  deleteBook(id: Int!): Boolean!
}

resolvers フォルダの Mutation.js を開きます。

Mutation 内にdeleteBookを作成します。

exports.Mutation = {
  addBook: (parent, { input }, { db }) => {
    const { id, title, author, categoryId, isRead } = input
    const newBook = {
      id,
      title,
      author,
      categoryId,
      isRead,
    }

    db.books.push(newBook)

    return newBook
  },
  deleteBook: (parent, { id }, { db }) => {},
}

特定のデータを抽出するために、filterを設定します。

また、成功したらtrueを返す様にしましょう。

deleteBook: (parent, { id }, { db }) => {
  db.books = db.books.filter((book) => book.id !== id);
  return true;
},

では、ブラウザで確認します。

今回は、id が『2』のデータを削除します。

image9

『DeleteBook』をクリックすると、

image10

trueが返ってきました。

全ての books データを取得すると、

image11

id が『2』のデータを削除することができました。

データを更新する

最後に、books データを更新します。

schema.js のMutationupdateBookを作成します。

type Mutation {
    addBook(input: AddBookInput!): Book!
    deleteBook(id: Int!): Boolean!
    updateBook
  }

変更内容を指定したいので、inputを作成します。

input UpdateBookInput {
    id: Int
    title: String
    author: String
    categoryId: String
    isRead: Boolean
  }

updateBook にidinputを指定します。

また、addBookと同様に、Bookを返す様にします。

type Mutation {
  addBook(input: AddBookInput!): Book!
  deleteBook(id: Int!): Boolean!
  updateBook(id: Int!, input: UpdateBookInput!): Book!
}

これでスキーマが完成しました。

次は、理ゾルバーを作成します。

resolvers フォルダの Mutation.js を開きます。

Mutationの中に、updateBookを作成します。

exports.Mutation = {
  addBook: (parent, { input }, { db }) => {
    const { id, title, author, categoryId, isRead } = input
    const newBook = {
      id,
      title,
      author,
      categoryId,
      isRead,
    }

    db.books.push(newBook)

    return newBook
  },
  deleteBook: (parent, { id }, { db }) => {
    db.books = db.books.filter(book => book.id !== id)
    return true
  },
  updateBook: (parent, { id, input }, { db }) => {},
}

index で何番目のデータを指定するかを設定します。

updateBook: (parent, { id, input }, { db }) => {
  const index = db.books.findIndex((book) => book.id === id);
},

指定したデータに、変更する内容と、それ以外の内容を指定します。

また、その内容を返します。

updateBook: (parent, { id, input }, { db }) => {
  const index = db.books.findIndex((book) => book.id === id);
  const updateData = (db.books[index] = {
    ...db.books[index],
    ...input,
  });
  return updateData;
},

では、ブラウザで確認します。

今回は、id が『3』の author を変更します。

image12

実行してみると、

image13

変更後の author が返ってきました。

image14

データも反映されています。

これで、データの追加、削除、更新ができました。

全文は、以下のコードです。

ブログ一覧