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

【GraphQL】特定の条件に合致したデータを抽出する
今回は、データを追加、削除、更新します。
GraphQL では、データを追加したり、削除、更新したりすることをミューテーションと言います。
コードは、前回のコードを使用します。
データを追加する
まずは、本のデータを追加します。
schema.js のdypeDefs内に、ミューテーションの方を作ります。
本を追加するミューテーションを作りたいので、名前をaddBookとします。
js
type Mutation {
addBook
}
addBookにBookを返す様にします。
js
type Mutation {
addBook: Book!
}
addBookの内容をinputで設定します。
設定内容は、bookのデータにします。
js
input AddBookInput {
id: Int!
title: String!
author: String!
categoryId: String!
isRead: Boolean!
}
addBookの中にAddBookInputを指定します。
js
type Mutation {
addBook(input: AddBookInput!): Book!
}
スキーマが完成したので、次はリゾルバーを作成します。
resolvers フォルダの中に、Mutation.js を作成します。
Mutationをエクスポートする様にします。
スキーマで設定した、addBookを追加します。
第二引数にinput、第三引数にbooksを指定します。
js
exports.Mutation = {
addBook: (parent, { input }, { books }) => {},
};
input から、『id』『title』『author』『categoryId』『isRead』を指定します。
また、newBookを作成します。
inputの内容を、newBookに記述します。
js
exports.Mutation = {
addBook: (parent, { input }, { books }) => {
const { id, title, author, categoryId, isRead } = input;
const newBook = {
id,
title,
author,
categoryId,
isRead,
};
},
};
newBookをbooksデータに追加します。
newBooksを返します。
js
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を追加します。
js
const server = new ApolloServer({
typeDefs,
resolvers: {
Query,
Mutation,
Category,
Book,
},
context: {
books,
categories,
},
});
今のところ、全ての books データを取得すると、エラーになります。
全てのデータを取得できるように、resolvers の Query.js で、id の指定がある場合のみ、filter を使う様にします。
js
books: (parent, { filter }, { db }) => {
let filteredBooks = db.books;
if (filter) {
if (filter.isRead === true) {
filteredBooks = filteredBooks.filter((book) => {
return book.isRead;
});
}
}
return filteredBooks;
},

books データの一覧が取得できました。
では、データが追加できるか、ブラウザで確認してみます。
GraphQL でデータを抽出するときは、queryを使いました。
今回は、mutationを使います。
graphql
mutation AddBook($input: AddBookInput!) {
addBook(input: $input) {
id
title
author
}
}

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

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

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

無事、データが追加されました。
データを削除する
次は、books データを削除します。
ここで作成したデータでは、GraphQL で削除が反映されないので、データをオブジェクト内で設定する様にします。
index.js のbooksとcategoriesをdbでまとめます。
js
const db = { books, categories };
context内もdbへ修正します。
js
const server = new ApolloServer({
typeDefs,
resolvers: {
Query,
Mutation,
Category,
Book,
},
context: {
db,
},
});
contextの部分を、全てdbに置き換えましょう。
resolvers/Query.js
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
js
exports.Category = {
books: ({ id }, args, { db }) => {
return db.books.filter((book) => book.categoryId === id);
},
};
resolvers/Book.js
js
exports.Book = {
category: ({ categoryId }, args, { db }) => {
return db.categories.find((category) => category.id === categoryId);
},
};
resolvers/Mutation.js
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;
},
};
一度、ブラウザで確認します。


うまく機能しています。
schema.js のMutationにdeleteBookを作成します。
指定はidを指定し、成功したかどうかを知りたいので、Booleanを返す様にします。
js
type Mutation {
addBook(input: AddBookInput!): Book!
deleteBook(id: Int!): Boolean!
}
resolvers フォルダの Mutation.js を開きます。
Mutation 内にdeleteBookを作成します。
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;
},
deleteBook: (parent, { id }, { db }) => {},
};
特定のデータを抽出するために、filterを設定します。
また、成功したらtrueを返す様にしましょう。
js
deleteBook: (parent, { id }, { db }) => {
db.books = db.books.filter((book) => book.id !== id);
return true;
},
では、ブラウザで確認します。
今回は、id が『2』のデータを削除します。

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

trueが返ってきました。
全ての books データを取得すると、

id が『2』のデータを削除することができました。
データを更新する
最後に、books データを更新します。
schema.js のMutationにupdateBookを作成します。
js
type Mutation {
addBook(input: AddBookInput!): Book!
deleteBook(id: Int!): Boolean!
updateBook
}
変更内容を指定したいので、inputを作成します。
js
input UpdateBookInput {
id: Int
title: String
author: String
categoryId: String
isRead: Boolean
}
updateBook にidとinputを指定します。
また、addBookと同様に、Bookを返す様にします。
js
type Mutation {
addBook(input: AddBookInput!): Book!
deleteBook(id: Int!): Boolean!
updateBook(id: Int!, input: UpdateBookInput!): Book!
}
これでスキーマが完成しました。
次は、理ゾルバーを作成します。
resolvers フォルダの Mutation.js を開きます。
Mutationの中に、updateBookを作成します。
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;
},
deleteBook: (parent, { id }, { db }) => {
db.books = db.books.filter((book) => book.id !== id);
return true;
},
updateBook: (parent, { id, input }, { db }) => {},
};
index で何番目のデータを指定するかを設定します。
js
updateBook: (parent, { id, input }, { db }) => {
const index = db.books.findIndex((book) => book.id === id);
},
指定したデータに、変更する内容と、それ以外の内容を指定します。
また、その内容を返します。
js
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 を変更します。

実行してみると、

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

データも反映されています。
これで、データの追加、削除、更新ができました。
全文は、以下のコードです。