【问题标题】:Nested sort in GraphQLGraphQL 中的嵌套排序
【发布时间】:2020-09-18 23:49:56
【问题描述】:

我使用 Contentful 作为 CMS,其中我有内容模型“类别”和“子类别”。每个子类别都有一个类别作为其父类别。这两个模型都有一个名为order 的属性,我在 CMS 中设置了它来决定它们在导航中出现的顺序。

这是我的 GraphQL 查询:

query {
  allContentfulCategory(sort: {fields: [order, subcategory___order]}) {
    edges {
      node {
        order
        title
        subcategory {
          order
          title
        }
      }
    }
  }
}

第一个排序工作正常,查询按 order 字段输出我的类别,而不是按似乎是 Contentful 的默认输出的反向创建顺序(最新类别首先显示)。

但是,受this blog post 启发的我的第二种subcategory___order 没有评估。换句话说,子类别(每个类别)以相反的顺序显示,因此顶部项目的顺序为 8,然后减少到 7 和 6,依此类推。

例如,假设我的类别“动物”的顺序为 2,而“树木”的类别为顺序 1。我的内容按逆向创建顺序:“猫”(顺序 3)、“狗”(顺序 1)、“鸡”(订单 2)、“桦木”(订单 2)、“橡木”(订单 3)和“柳树”(订单 1)。

这些将像这样通过查询:

Trees (1):
  Birch (2)
  Oak (3)
  Willow (1)
Animals (2):
  Cat (3)
  Dog (1)
  Chicken (2)

我找不到让 GraphQL 查询同时执行两个排序命令的方法,以便我的数据按照我在 CMS 中设置的顺序进行排序。

提前非常感谢!

编辑:这是一个组件解决方案:

在来自我的查询的每个类别节点中,我可以访问子类别及其在数组中的顺序。

const categories = data.allContentfulCategory.edges
    {categories.map((category) => {
        return (
            <div>
                {category.node.subcategory && category.node.subcategory.sort((a, b) => {return a.order - b.order}).map((subcategory) => {
                    return (
                        <div>
                            <p>{subcategory.title}</p>
                        </div>
                    )
                })}
            </div>
         )
      })}

这里的关键元素是我如何按组件内的子类别顺序对数组进行排序:

category.node.subcategory.sort((a, b) =&gt; {return a.order - b.order})

需要明确的是,这不是一个令人满意的解决方案,也没有回答我关于如何编写多个 GraphQL 排序的问题。但是这段代码在组织子类别方面确实符合我的要求。

【问题讨论】:

标签: reactjs graphql gatsby


【解决方案1】:

您查询的是category 而不是subcategory

query {
  allContentfulCategory(sort: {fields: [order, subcategory___order]}) {
    edges {
      node {
        order
        title
        subcategory {
          order
          title
        }
      }
    }
  }
}

在上面的查询中,只对返回的数组data.allContentfulCategory.edges 进行了排序。 Gatsby 不会对嵌套在 category.subcategory 中的数据进行排序。

此外,只有当第一个字段 (order) 相同时,才会考虑您指定的第二个字段 (subcategory___order)。由于每个类别都有唯一的顺序,因此永远不会使用subcategory

如果您可以改为查询 allContentfulSubcategory 之类的内容,它会起作用。

否则,您可以使用createSchemaCustomization 将排序逻辑移动到构建时间。我不知道你的架构是什么样的,所以这只是一个例子:

// gatsby-node.js
exports.createSchemaCustomization = ({ actions, schema }) => {
  const { createTypes } = actions
  const typeDefs = [
    schema.buildObjectType({
      name: "ContentfulCategory",
      fields: {
        subcategory: {
          type: "[ContentfulSubcategory]",
          resolve: (src) => {
            const subcategories = src.subcategory
            return subcategories.sort()
          }
        },
      },
      interfaces: ["Node"],
      extensions: { infer: true },
    }),
  ]
  createTypes(typeDefs)
}

如果您需要使用createSchemaCustomization,请参阅the Gatsby docs on the topic here

文档的信息可能是压倒性的,我也是wrote a bit about this API here。更多的是字段扩展,但解析器功能基本相同。

【讨论】:

  • 感谢您解释问题所在,并提供看起来非常优雅的解决方案。您可能会在我对问题的编辑中看到我找到了基于组件的解决方案。你能说一下哪个对性能/实践等更好,createSchemaCustomization 还是只是在组件级别排序?顺便说一下,在您的博客上进行整洁的设计!
  • 谢谢@22moonriver!我认为在实践中,除非您有大量数据,否则在组件中执行排序没有区别。使用 createSchemaCustomization,排序只会在 gatsby 构建期间执行,而不是在客户端中执行(就像基于组件的解决方案一样。)
猜你喜欢
  • 2018-09-13
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 2022-06-27
  • 1970-01-01
  • 2020-11-28
  • 2018-01-16
  • 1970-01-01
相关资源
最近更新 更多