【问题标题】:GraphQL: Filter data in an arrayGraphQL:过滤数组中的数据
【发布时间】:2017-05-21 18:41:00
【问题描述】:

我确信这很简单,但我在 GraphQL 的文档或 Graphcool 的文档中都找不到任何内容。

假设我有一个具有此架构的实体(GraphQL 新用户,如果我在架构表示中犯了错误,请见谅):

Book {
  name: String!
  author: String!
  categories: [String!]
}

如何查询属于"mystery" 类别的所有书籍?我知道我可以使用allBooks(filter: {}) 进行过滤,但是categories_in: ["mystery"]categories_contains: "mystery" 没有做到这一点。

【问题讨论】:

  • Graphcool 目前不支持此功能。我添加了一个功能请求来跟踪这个:github.com/graphcool/feature-requests/issues/60
  • 嗯,很高兴知道。我会去 +1 你的问题。让我们希望我们能尽快得到这个!
  • 当前的解决方法可能是引入与Book 具有多对多关系的新模型Category。然后你可以这样做:allCategories(filter: {tag: "mystery"}) { books { id } }。我想拥有Category 模型可能对未来的元数据或类似的东西有利。

标签: graphql graphcool


【解决方案1】:

Category型号

多考虑一下这种情况,创建一个Category 模型绝对是要走的路。

例如,假设您希望允许读者稍后订阅他们喜欢的类别。或者,如果您想要所有现有类别的列表怎么办?使用字符串列表,您需要查询所有书籍并以某种方式对所有获得的类别进行后处理。在模型级别而不是使用字符串列表来处理这个感觉更自然。

相反,您可以创建一个新的Category 模型并在CategoryBook 之间添加多对多关系。在这种情况下,我喜欢添加一个唯一的枚举字段tag 和一个字符串字段text。 (单独一个唯一的字符串字段tag 也是合适的,可能是个人喜好问题。)

通过此设置,您可以轻松满足数据要求,例如

哪些书属于给定类别?

query {
  # query books by unique category tag
  Category(tag: MYSTERY) {
    books {
      id
    }
  }
  # query books by specific category text
  Category(filter: {
    text: "mystery"
  }) {
    books {
      id
    }
  }
}

哪些书被分配到给定列表的至少一个类别中?

query {
  allCategories(filter: {
    OR: [{
      tag: MYSTERY
    }, {
      tag: MAGIC
    }]
  }) {
    books {
      id
    }
  }
}

哪些书被分配到给定列表的所有类别中?

query {
  allCategories(filter: {
    AND: [{
      tag: MYSTERY
    }, {
      tag: MAGIC
    }]
  }) {
    books {
      id
    }
  }
}

相关过滤器

尽管上述查询满足了指定的数据要求,但图书在响应中仍按Category 分组,这意味着我们必须在客户端上展平这些组。

使用所谓的相关过滤器,我们可以扭转这种局面,仅根据定义其相关类别的条件获取书籍。

例如,查询分配给给定列表的至少一个类别的书籍

query {
  allBooks(filter: {
    OR: [{
      categories_some: {
        tag: MYSTERY
      },
      categories_some: {
        tag: MAGIC
      }
    }]
  }) {
    id
  }
}

【讨论】:

  • 不幸的是,它并没有真正回答这个问题。我正在尝试查询 shopify 产品,每个产品都包含一个标签数组,这些标签是字符串。我想不可能查询所有包含给定标签的产品?!唔。解决方案:获取所有产品并在客户端过滤!
【解决方案2】:

如果您对使用托管 GraphQL 服务感兴趣,scaphold.io 已经有一段时间了。 API 中的所有连接字段都带有 WhereArgs 参数,该参数公开过滤器,让您真正深入挖掘数据。当您有这样的标量列表时, WhereArgs 包含一个 containsnotContains 字段,允许您根据列表中的值过滤结果。这允许您进行这样的查询。

query MysteriousBooks($where:BookWhereArgs) {
  viewer {
    allBooks(where:$where) {
      edges { node { title, ... } }
    }
  }
}

# Variables
{
  "where": {
    "categories": {
      "contains": "mystery"
    }
  }
}

为了完整起见,您还可以对架构进行轻微的调整以使其正常工作,而无需在标量列表上进行过滤。例如,您可以使Category 成为一个节点实现类型,然后在CategoryBook 之间创建一个连接。尽管Book 可能没有很多类别,但这将允许您发出这样的查询:

query MysteriousBooks($where: CategoryWhereArgs) {
  viewer {
    allCategories(where: $where) {
      books {
        edges { node { title, ... } }
      }
    }
  }
}

# Variables
{
  "where": { 
    "name": { 
      "eq": "mystery" 
    } 
  }
}

如果您以这种方式构建架构,那么您还可以对类别中的书籍进行更多过滤,而无需遍历存档中的每本书。例如。你可以有效地要求“去年写的所有神秘书籍”。

完全披露:我在 Scaphold 工作,尽管如果你不转职,我希望你能尝试一下,不会有任何难过的感觉。我很高兴看到人们尝试和喜爱 GraphQL。如果您对如何在自己的服务器上实现此类行为感到好奇,请告诉我,我也很乐意为您提供帮助!

我希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-04
    • 2022-01-01
    • 2021-02-09
    • 2021-08-31
    • 2021-01-06
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多