I am not using AWS AppSync for this app. I have created Graphql schema, I have made my own resolvers. For each create, query, I have made each Lambda functions. I used DynamoDB Single table concept and it's Global secondary indexes.
It was ok for me, to create an Book item. In DynamoDB, the table looks like this: .
I am having issue with the return Graphql queries. After getting the Items
from DynamoDB table, I have to use Map function then return the Items
based on Graphql type
. I feel like this is not efficient way to do that. Idk the best way query data. Also I am getting null both author and authors query.
This is my gitlab-branch.
This is my Graphql Schema
import { gql } from 'apollo-server-lambda';
const typeDefs = gql`
enum Genre {
adventure
drama
scifi
}
enum Authors {
AUTHOR
}
# Root Query - all the queries supported by the schema
type Query {
"""
All Authors query
"""
authors(author: Authors): [Author]
books(book: String): [Book]
}
# Root Mutation - all the mutations supported by the schema
type Mutation {
createBook(input: CreateBook!): Book
}
"""
One Author can have many books
"""
type Author {
id: ID!
authorName: String
book: [Book]!
}
"""
Book Schema
"""
type Book {
id: ID!
name: String
price: String
publishingYear: String
publisher: String
author: [Author]
description: String
page: Int
genre: [Genre]
}
input CreateBook {
name: String
price: String
publishingYear: String
publisher: String
author: [CreateAuthor]
description: String
page: Int
genre: [Genre]
}
input CreateAuthor {
authorName: String!
}
`;
export default typeDefs;
This is I created the Book Item
import AWS from 'aws-sdk';
import { v4 } from 'uuid';
import { CreateBook } from '../../generated/schema';
async function createBook(_: unknown, { input }: { input: CreateBook }) {
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const id = v4();
const authorsName =
input.author &&
input.author.map(function (item) {
return item['authorName'];
});
const params = {
TableName: process.env.ITEM_TABLE ? process.env.ITEM_TABLE : '',
Item: {
PK: `AUTHOR`,
SK: `AUTHORS#${id}`,
GSI1PK: `BOOKS`,
GSI1SK: `BOOK#${input.name}`,
name: input.name,
author: authorsName,
price: input.price,
publishingYear: input.publishingYear,
publisher: input.publisher,
page: input.page,
description: input.description,
genre: input.genre,
},
};
await dynamoDb.put(params).promise();
return {
...input,
id,
};
}
export default createBook;
This is how query the All Book
import AWS from 'aws-sdk';
async function books(_: unknown, input: { book: string }) {
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: process.env.ITEM_TABLE ? process.env.ITEM_TABLE : '',
IndexName: 'GSI1',
KeyConditionExpression: 'GSI1PK = :hkey',
ExpressionAttributeValues: {
':hkey': `${input.book}`,
},
};
const { Items } = await dynamoDb.query(params).promise();
const allBooks = // NEED TO MAP THE FUNcTION THEN RETURN THE DATA BASED ON GRAPHQL //QUERIES.
Items &&
Items.map((i) => {
const genre = i.genre.filter((i) => i);
return {
name: i.name,
author: i.author,
genre,
};
});
return allBooks;
}
export default books;
This my Author query and Image of the console result
import AWS from 'aws-sdk';
import { Author, Authors } from '../../generated/schema';
async function authors(
_: unknown,
input: { author: Authors }
): Promise<Author> {
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: process.env.ITEM_TABLE ? process.env.ITEM_TABLE : '',
KeyConditionExpression: 'PK = :hkey',
ExpressionAttributeValues: {
':hkey': `${input.author}`,
},
};
const { Items } = await dynamoDb.query(params).promise();
console.log({ Items }); // I can see the data but don't know how to returns the data like this below type without using map function
// type Author {
// id: ID!
// authorName: String
// book: [Book]!
// }
return Items; // return null in Graphql play ground.
}
export default authors;
Edit: current resolver map
// resolver map - src/resolvers/index.ts
const resolvers = {
Query: {
books,
authors,
author,
book,
},
Mutation: {
createBook,
},
};