【问题标题】:graphql - combining results from multiple queries into one arraygraphql - 将多个查询的结果组合到一个数组中
【发布时间】:2018-07-29 18:54:59
【问题描述】:

我正在使用 graphQL 通过组合查询来跨多个 mongoDB 集合和 API 执行搜索。所有查询都返回一个结果类型

{
  _id: string; 
  name: string; 
  type: string;
}

有没有办法将数据扁平化成一个数组?

组合查询示例:

query searchAll {
    books(input: {text: "e"}) {
        _id
        name
        type
    }
    magazines(input: {text: "e"}) {
        _id
        name
        type
    }
}

目前的响应如下:

{"data": {
        "books": [
            {
                "_id": "5a8ac759c25b7235ffdc6888",
                "name": "someBook",
                "type": "book"
            }
        ],
        "magazines": [
            {
                "_id": "5a87005bc25b7235ffdc4bdf",
                "name": "someMagazine-1",
                "type": "magazine"
            },
            {
                "_id": "5a870067c25b7235ffdc4be4",
                "name": "someMagazine-2",
                "type": "client"
            }
        ]
    }
}

期望的响应:

{"data": {
    "results": [
            {
                "_id": "5a8ac759c25b7235ffdc6888",
                "name": "someBook",
                "type": "book"
            },
            {
                "_id": "5a87005bc25b7235ffdc4bdf",
                "name": "someMagazine-1",
                "type": "magazine"
            },
            {
                "_id": "5a870067c25b7235ffdc4be4",
                "name": "someMagazine-2",
                "type": "client"
            }
        ]
    }
}

【问题讨论】:

    标签: graphql graphql-js


    【解决方案1】:

    您想研究使用接口,这是一个(稍微丰富的)模式定义的示例:

    interface Searchable {
      id: ID!
      name: String!
    }
    
    type Book implements Searchable {
      id: ID!
      name: String!
      author: Author!
      publisher: Publisher!
      isbn: String!
    }
    
    type Magazine implements Searchable {
      id: ID!
      name: String!
      publisher: Publisher!
      issn: String!
    }
    
    input SearchInput {
      text: String!
    }
    
    type Query {
      search(input: SearchInput!): [Searchable!]!
    }
    

    以下是查询的方式:

    query searchAll {
      search(input: {text: "e"}) {
        __typename
        id
        name
        ... on Book {
          author
          isbn
        }
        ... on Magazine {
          issn
        }
      }
    }
    

    search 的解析器将负责调用所有不同的集合并将结果聚合到单个数组中。比这更深入的是特定于实现的,但应该有文档用于在您使用的任何 GraphQL 实现中使用接口(和类似的联合)。

    __typename 字段告诉您返回对象的具体类型,从而让前端代码执行适当的显示逻辑。

    【讨论】:

    • 感谢您的回复。我查看了接口,根据您的建议,我有几个问题: 1. 如果 book 和 magazine 总是类型 Searchable,但来自不同的数据库(不需要添加额外的唯一字段)怎么办? 2. 搜索解析器的外观如何? (与单个 BooksMagazines 解析器相比)
    • 我明白了。我想我在考虑 graphQL 错误(刚开始使用它)。我认为重点是不要创建一个长的 API 聚合器,而是编写不同的查询 + 解析器并根据需要灵活地使用它们。在上面的示例中,我想我可以编写 4 个不同的查询 + 解析器来搜索 4 个数据库,然后能够根据需要查询全部或其中的一个子集。而不是编写一个从所有 4 个数据库中获取数据的长解析器。
    • 将结果聚合到一个解析器的主要好处是什么?使用相应的解析器运行单个查询?再次感谢!
    • 最终选择两种方法(一个搜索字段与多个)的原因将归结为您想要的客户端行为。如果您的最终结果本质上是单个分页列表,则首选单个字段(使用接口)。但这会使分页逻辑变得复杂,因为您需要跨数据源对其进行协调,这通常意味着为每个源获取一整页并丢弃溢出。
    • 如果您不需要这种单一的大型搜索搜索行为,那么您最初拥有的可能是一个更好的起点。这绝对是一种来自产品需求的决定,而不是一种技术上优越的方法。
    猜你喜欢
    • 2019-07-11
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 2021-10-09
    • 1970-01-01
    相关资源
    最近更新 更多