简体   繁体   English

GraphQL如何仅在需要时使解析器获取数据?

[英]GraphQL how to make resolver fetch data only if needed?

I have two GraphQL type: 我有两种GraphQL类型:

type Author {
  id: String!
  name: String!
}

type Book {
  id: String!
  author: Author!
  name: String!
}

In my database, it is implemented by a foreign key inside the books table: 在我的数据库中,它是由books表中的外键实现的:

table authors (pseudo code) authors (伪代码)

`id` INTEGER UNSIGNED
`name` STRING

table books (pseudo code) books (伪代码)

`id` INTEGER UNSIGNED
`author_id` INTEGER UNSIGNED REFERENCE `authors.id`
`name` STRING

So when I resolve a GraphQL query like: 因此,当我解析GraphQL查询时:

query allTheBooks {
  id
  name
  author {
    id
  }
}

I dont want to do another SQL query than the one that will get the list of books, as I already have the data in the books.author_id field. 除了要获取书籍列表的查询之外,我不想执行其他SQL查询,因为我已经在books.author_id字段中包含了数据。

So I replace the following code (js): 因此,我替换了以下代码(js):

Book: {
  async author(book, args, context, info) {
    // this code trigger a database SELECT query that fetch all the fields of the author row associated with the book
    return book.author().get();
  }
}

by: 通过:

Book: {
  async author(book, args, context, info) {
    return {
      id: book.author_id,
    }
  }
}

And it work well ! 而且效果很好!

I only have 1 SQL query where I had 1 + N (N is the number of rows returned by the first query). 我只有1个SQL查询,其中我有1 + N(N是第一个查询返回的行数)。

But how can I return the other fields without sending a query by field ? 但是,如何在不按字段发送查询的情况下返回其他字段?

I imagine that it's possible by returning an unique promise for all the fields, that will resolve with the all the content of the author row, but I wonder if there is a cleaner way... 我想这有可能通过为所有字段返回一个唯一的promise来解决author行的所有内容,但是我想知道是否有更干净的方法...

Thank you in advance for your answer ! 预先感谢您的答复!

For now, I find a more or less clean way to do this: 就目前而言,我发现一种或多或少的干净方法可以做到这一点:

Book: {
  async author(book, args, context, info) {
    let authorPromise = null;

    async function getAuthor() {
      if (authorPromise === null) {
        authorPromise = book.author().get();
      }

      return authorPromise;
    }

    return new Proxy({}, {
      async get({}, name) {
        if (name === "id") {
          return book.author_id;
        }

        if (name in authorFields) {
          const author = await getFile();
          return author[name];
        }
      },
    });
  }
}

It ensure me to do only one query per row, but leave me with another question about the joining of the tables, but I'll post it here :-) 它确保我每行只执行一个查询,但又给我一个关于表联接的问题,但我将其发布在这里 :-)

You don't have to make 1 + N query. 您不必进行1 + N查询。 You can batch N queries into 1. Just check out https://github.com/facebook/dataloader . 您可以将N个查询批处理为1个。只需签出https://github.com/facebook/dataloader即可

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

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