查询放大graphql多对多关系

Posted

技术标签:

【中文标题】查询放大graphql多对多关系【英文标题】:querying amplify graphql many-to-many relationship 【发布时间】:2021-01-13 04:04:18 【问题描述】:

我正在通过创建一个库来探索使用 typescript 进行放大,并建立了多对多连接

type Book @model 
  # ! means non-null GraphQL fields are allowed to be null by default
  id: ID!
  name: String!
  picture: String!
  genres: [BookGenre] @connection(keyName: "byBook", fields: ["id"])
  createdAt: String!
  userId: String!


type BookGenre
@model(queries: null)
@key(name: "byBook", fields: ["bookID", "genreID"])
@key(name: "byGenre", fields: ["genreID", "bookID"]) 
  id: ID!
  bookID: ID!
  genreID: ID!
  book: Book! @connection(fields: ["bookID"])
  genre: Genre! @connection(fields: ["genreID"])


type Genre @model 
  id: ID!
  name: String!
  createdAt: String!
  books: [BookGenre] @connection(keyName: "byGenre", fields: ["id"])

我可以创建一本新书并添加用户提供的此类类型

const handleSubmit = async (evt) => 
        evt.preventDefault();
        const createdAt = new Date().toISOString();
        const bookID = hash(name);
        const book: CreateBookInput = 
            id: bookID,
            name,
            picture: "",
            createdAt: createdAt,
            userId: "faked"
        ;
        try 
            await API.graphql(
                graphqlOperation(createBook, 
                    input: book
                )
            );
            for (const t of tags) 
                const genreID = hash(t)
                const genre: CreateGenreInput = 
                    id: genreID, name: t, createdAt
                
                await API.graphql(graphqlOperation(createGenre, input: genre))

                const bookGenre: CreateBookGenreInput = 
                    bookID, genreID
                
                await API.graphql(graphqlOperation(createBookGenre, input: bookGenre))
            

            setName("")
         catch (e) 
            console.error(e)
        
    

这可能不是最好的方法!因为每本书都写了很多,但我可以看到流派及其连接记录被写入 Dynamo

我想加载一个列出所有书籍的页面。

我是这样做的:

    let result;
    try 
        result = await API.graphql(graphqlOperation(listBooks));
     catch (err) 
        console.warn(err);
        return  props:  books: [] ;
    
    if (result.errors) 
        console.warn("Failed to fetch books. ", result.errors);
        return  props:  books: [] ;
    
    
    const queryResult: ListBooksQuery = result.data
    if (queryResult.listBooks !== null) 
        let books = queryResult.listBooks.items
        return  props:  books ;
    

    return  props:  books: [] ;

但这不会加载流派...

我猜我需要通过@key(name: "byBook", fields: ["bookID", "genreID"]) 进行查询,但我不明白如何通过查看生成的代码来做到这一点...

我是新来的放大和graphql,所以我假设我错过了一些微不足道的东西:)

通过多对多关系查询所有项目及其子项的列表的正确方法是什么?

【问题讨论】:

您找到解决方案了吗?尽管文档 (docs.amplify.aws/cli/graphql-transformer/…) 说我“只”需要调用 Book.genres,但遇到了同样的问题。令人沮丧。 插入数据时const bookGenre: CreateBookGenreInput = bookID, genreID 为什么不提供BookGenre ID? 此外,GraphQL 连接在创建时会询问您需要连接的深度级别,您可以仔细检查是否有值 2 或 【参考方案1】:

amplify 似乎没有正确生成查询。

我假设您生成的查询看起来像这样:

export const listBooks = /* GraphQL */ `
  query ListBooks(
    $filter: ModelBookFilterInput
    $limit: Int
    $nextToken: String
  ) 
    listBooks(filter: $filter, limit: $limit, nextToken: $nextToken) 
      items 
        id
        name
        picture
        genres 
          nextToken
        
        createdAt
        userId
      
      nextToken
    
  
`;

为了同时加载Genre,您需要将查询修改为:

export const listBooks = /* GraphQL */ `
  query ListBooks(
    $filter: ModelBookFilterInput
    $limit: Int
    $nextToken: String
  ) 
    listBooks(filter: $filter, limit: $limit, nextToken: $nextToken) 
      items 
        id
        name
        picture
        genres 
          items 
            genre 
              name
            
          
          nextToken
        
        createdAt
        userId
      
      nextToken
    
  
`;

genres.items 将加载连接表中的所有实体。 然后genre 将在实体上加载该字段,该字段引用Genre 表。

【讨论】:

以上是关于查询放大graphql多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

在 TypeORM 与 GraphQL 的多对多关系上使用数据加载器,查询多对多

如何在graphql突变中设置多对多关系?

具有多对多关系的类型元素的 GraphQL 解析器

GraphQL 中的多对多关系

GraphQL Apollo 中的多对多关系

从多对多关系中获取结果