You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GraphQL批量查询图书数据:如何用GraphQLList遍历ISBN数组

如何在GraphQL中实现批量图书查询(对接Amazon/Itunes API)

看起来你已经有了单本图书查询的基础,要实现批量查询其实只需要调整几个关键地方:参数类型改为数组、批量处理API请求,以及调整返回结构匹配你的需求。我来一步步给你修改示例:

1. 调整RootQuery:支持接收ID数组并批量返回数据

首先要把id参数的类型从单个字符串改成字符串数组,这里就用到了你提到的GraphQLList。同时,我们需要在resolve函数里遍历每个ID,并行发起API请求,最后整理成你期望的响应格式。

修改后的RootQuery.js代码:

const graphql = require('graphql');
const { GraphQLObjectType, GraphQLString, GraphQLList } = graphql;
const BookType = require('../types/book');

const RootQuery = new GraphQLObjectType({
  name:'RootQuery',
  fields: () => ({
    book: {
      // 自定义类型匹配你需要的对象结构(book1、book2...)
      type: new GraphQLObjectType({
        name: 'BookBatchResult',
        fields: () => ({})
      }),
      args:{ 
        id : { type: new GraphQLList(GraphQLString) } // 用GraphQLList接收ID数组
      },
      async resolve (parentValue, args) {
        // 遍历每个ID,创建获取单本图书数据的Promise
        const bookTasks = args.id.map(async (bookId) => {
          // 仅返回ID,BookType里的itunes/amazon字段会自动触发对应resolve
          return { id: bookId };
        });

        // 等待所有请求完成
        const books = await Promise.all(bookTasks);

        // 转换为你需要的book1、book2格式
        const result = {};
        books.forEach((book, index) => {
          result[`book${index + 1}`] = book;
        });

        return result;
      }
    }
  })
});

module.exports = RootQuery;

2. 修复BookType的异步处理逻辑

你的BookType里的resolve函数没有处理异步操作,而调用Amazon/Itunes API肯定是异步的,所以必须改成async/await确保数据正确返回,同时处理无数据的情况:

修改后的BookType.js代码:

const graphql = require('graphql');
const { GraphQLObjectType, GraphQLString } = graphql;
const itunes = require('../connections/itunes');
const ItunesType = require('./itunes');
const amazon = require('../connections/amazon');
const AmazonType = require('./amazon');

const BookType = new GraphQLObjectType({
  name:'book',
  fields: () => ({
    id: { type: GraphQLString },
    itunes: { 
      type: ItunesType, 
      async resolve(parentValue){
        try {
          const data = await itunes.getMetadataItunes(parentValue.id);
          // API返回空时返回"不可用"提示
          return data || { title: "Niet beschikbaar" };
        } catch (err) {
          // 捕获错误,返回统一提示
          return { title: "Niet beschikbaar" };
        }
      } 
    },
    amazon: { 
      type: AmazonType, 
      async resolve(parentValue) {
        try {
          const data = await amazon.getMetadataAmazon(parentValue.id);
          return data || { title: "Niet beschikbaar" };
        } catch (err) {
          return { title: "Niet beschikbaar" };
        }
      } 
    }
  })
});

module.exports = BookType;

3. 可选:改用数组返回(更符合GraphQL规范)

其实GraphQL更推荐返回数组格式,因为它的结构更灵活,前端处理起来也更简单。如果改成数组返回,你只需要把RootQuery里的返回类型改成new GraphQLList(BookType),resolve直接返回await Promise.all(bookTasks)即可:

修改后的RootQuery片段:

book: {
  type: new GraphQLList(BookType), // 返回BookType数组
  args:{ 
    id : { type: new GraphQLList(GraphQLString) }
  },
  async resolve (parentValue, args) {
    const bookTasks = args.id.map(async (bookId) => {
      return { id: bookId };
    });
    return await Promise.all(bookTasks);
  }
}

对应的响应会变成:

{
  "data": {
    "book": [
      {
        "amazon": { "title": "De Moord op Commendatore" },
        "itunes": { "title": "Niet beschikbaar" }
      },
      {
        "amazon": { "title": "Origin" },
        "itunes": { "title": "Origin" }
      }
    ]
  }
}

前端可以用一行代码把数组转成你想要的对象格式:

const bookObj = books.reduce((acc, book, idx) => ({...acc, [`book${idx+1}`]: book}), {})

关键知识点总结

  • GraphQLList的使用:在RootQuery的args里给id字段指定new GraphQLList(GraphQLString),就能接收ID数组了。
  • 异步处理:所有API请求必须用async/await或Promise处理,否则GraphQL无法获取异步返回的数据。
  • 错误处理:在resolve里加上try/catch,避免单个API请求失败导致整个批量查询崩溃。

内容的提问来源于stack exchange,提问作者Elvira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:42:17