简体   繁体   English

AWS Graphql lambda 查询

[英]AWS Graphql lambda query

I am not using AWS AppSync for this app .我没有为此应用程序使用 AWS AppSync I have created Graphql schema, I have made my own resolvers.我已经创建了 Graphql 架构,我已经制作了自己的解析器。 For each create, query, I have made each Lambda functions.对于每个创建、查询,我都做了每个 Lambda 函数。 I used DynamoDB Single table concept and it's Global secondary indexes.我使用了 DynamoDB 单表概念,它是全局二级索引。

It was ok for me, to create an Book item.对我来说可以,创建一个 Book 项目。 In DynamoDB, the table looks like this:在 DynamoDB 中,该表如下所示: 在此处输入图像描述 . .

I am having issue with the return Graphql queries.我遇到了返回 Graphql 查询的问题。 After getting the Items from DynamoDB table, I have to use Map function then return the Items based on Graphql type .从 DynamoDB 表中获取Items后,我必须使用 Map function 然后返回基于 Graphql typeItems I feel like this is not efficient way to do that.我觉得这不是有效的方法。 Idk the best way query data. Idk 查询数据的最佳方式。 Also I am getting null both author and authors query.我也收到 null 作者和作者的查询。

This is my gitlab-branch .这是我的gitlab-branch

This is my Graphql Schema这是我的 Graphql 架构

 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编辑:当前旋转变压器 map

// resolver map - src/resolvers/index.ts
const resolvers = {
  Query: {
    books,
    authors,
    author,
    book,
  },
  Mutation: {
    createBook,
  },
};

TL;DR You are missing some resolvers. TL;DR您缺少一些解析器。 Your query resolvers are trying to do the job of the missing resolvers.您的查询解析器正在尝试完成缺失解析器的工作。 Your resolvers must return data in the right shape.您的解析器必须以正确的形状返回数据。

In other words, your problems are with configuring Apollo Server's resolvers.换句话说,您的问题在于配置 Apollo Server 的解析器。 Nothing Lambda-specific, as far as I can tell.据我所知,没有什么 Lambda 特定的。

Write and register the missing resolvers.编写并注册缺少的解析器。

GraphQL doesn't know how to "resolve" an author's books, for instance.例如,GraphQL 不知道如何“解决”作者的书籍。 Add a Author {books(parent)} entry to Apollo Server's resolver map .Author {books(parent)}条目添加到 Apollo Server 的解析器 map The corresponding resolver function should return a list of book objects (ie [Books] ), as your schema requires.相应的解析器 function 应该根据您的架构要求返回书籍对象列表(即[Books] )。 Apollo's docs have a similar example you can adapt. Apollo 的文档有一个类似的例子,你可以修改。

Here's a refactored author query, commented with the resolvers that will be called:这是一个重构的author查询,带有将被调用的解析器的注释:

query author(id: '1') {     # Query { author } resolver
  authorName
  books {                   # Author { books(parent) } resolver
    name
    authors {               # Book { author(parent) } resolver
      id
    }
  }
}

Apollo Server uses the resolver map during query execution to decide what resolvers to call for a given query field. Apollo Server 在查询执行期间使用解析器 map 来决定为给定查询字段调用哪些解析器。 It's not a coincidence that the map looks like your schema. map 看起来像您的架构并非巧合。 Resolver functions are called with parent, arg, context and info arguments, which give your functions the context to fetch the right records from the data source.解析器函数使用parent、arg、context 和 info arguments 调用,这为您的函数提供了从数据源获取正确记录的上下文。

// resolver map - passed to the Apollo Server constructor
const resolvers = {
  Query: {
    books,
    authors,
    author,
    book,
  },

  Author: {
    books(parent) { getAuthorBooks(parent); }, // parent is the author - resolver should return a list of books
  },

  Book: {
    authors(parent) { getBookAuthors(parent); }, // parent is the book - resolver should return a list of authors
  },
};

Your query resolvers are trying to do too much work.您的查询解析器正试图做太多的工作。

It's not the author query resolver's job to resolve all the child fields.解析所有子字段不是作者查询解析器的工作。 Apollo Server will call multiple resolvers multiple times during query execution : Apollo Server 将在查询执行期间多次调用多个解析器:

You can think of each field in a GraphQL query as a function or method of the previous type which returns the next type.您可以将 GraphQL 查询中的每个字段视为 function 或返回下一个类型的上一个类型的方法。 In fact, this is exactly how GraphQL works.事实上,这正是 GraphQL 的工作原理。 Each field on each type is backed by a function called the resolver which is provided by the GraphQL server developer.每种类型的每个字段都由 function 支持,称为解析器,由 GraphQL 服务器开发人员提供。 When a field is executed, the corresponding resolver is called to produce the next value当一个字段被执行时,会调用相应的解析器来产生下一个值

Apollo Server calls this the resolver chain . Apollo Server 将此称为解析器链 The books(parent) resolver will be invoked with Author as its parent argument.将使用Author作为parent参数调用books(parent)解析器。 You can use the author id to look up her books.您可以使用作者 ID 来查找她的书籍。

Your resolver return values must be consistent with the schema.您的解析器返回值必须与架构一致。

Make sure your resolvers are returning data in the shape required by the schema.确保您的解析器以架构所需的形状返回数据。 Your author resolver is apparently returning a map {Items: [author-record]} , but your schema says it needs to be a list.您的author解析器显然返回了 map {Items: [author-record]} ,但您的架构说它需要是一个列表。

(If I were you, I would change the author query signature from author(PK: String, SK: String): [Author] to something more caller-friendly like author(id: ID): Author . Return an Object, not a List. Hide the DynamoDB implementation details in the resolver function. Apollo Server has a ID scalar type that is serialised as a String .) (如果我是你,我会将作者查询签名从author(PK: String, SK: String): [Author]更改为对调用者更友好的东西,例如author(id: ID): Author 。返回 Object,而不是列表。在解析器 function 中隐藏 DynamoDB 实现细节。Apollo Server 有一个被序列化为 StringID标量类型。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM