使用GraphQL更快地检索Shopify元字段

Shopify metafields

如果你是在Shopify平台上工作的应用程序开发人员,你可能知道许多商家将额外的产品数据存储在他们商店的Shopify元字段中。这对开发人员来说是一个挑战,因为通过Shopify REST API从元字段检索数据是出了名的困难,并且在同步客户端存储数据时可能会导致性能变慢。

我们的应用程序,Klevu Search,涉及检索商家的产品数据,并将其编入索引以供搜索。我们最初在元字段方面遇到了困难,但通过一些仔细的查询创建和资源管理,我们发现GraphQL可以比REST更快地用于获取产品元字段数据。但是,由于查询成本和节流的结合,GraphQL也有一个分点,在这个分点上它会比REST慢。

但是收益仍然是真实的:对于一些测试用例,我们能够将产品元字段的同步时间从4分钟减少到仅10秒。在本文中,我们将分享我们是如何做到这一点的,以及我们在这一过程中学到的有用信息。

通过REST API获取Shopify元字段

使用REST API检索存储在客户端产品上的元域数据的问题是无法批量检索它们。在Shopify文档中可以找到一些有希望的线索,例如/ metafields.json吗?metafield [owner_resource] =产品.然而,在实践中,这些方法并不返回我们所希望的数据。

因此,我们必须一次获取一个产品的元域数据,或者一次获取一个产品的变体。这意味着如果您的客户端拥有一个包含100个产品和400个变体的商店,那么您需要调用500个API来获得所有的元字段数据。我们发现这可能需要大约4分钟,这太长了。

通过GraphQL获取Shopify元字段

幸运的是,Shopify也有一个GraphQL API这允许在批量检索数据方面有更多的灵活性,并且可以用于更有效地检索产品元字段。

也就是说,这不仅仅是用对应的GraphQL调用替换REST调用的问题。需要进行一些仔细的查询创建和资源管理,我们将在下面的部分中深入讨论。

查询成本

最重要的是要理解GraphQL的查询成本。更多信息可在Shopify文档,但我们将在本文中介绍您需要了解的内容。

获取50个产品的名称和描述的GraphQL查询如下所示:

此查询结果的每个元素都有关联的资源成本。将产品数量从50增加到100会导致整体查询成本的增加,而将产品数量减少到10则会降低成本。

Shopify文档

模式中的每个字段都有分配给它的整型成本值。查询的开销是每个字段开销的总和。根据第一个或最后一个参数,连接字段对其子选择的代价具有乘法效应。”

让我们来看看一个最佳情况查询,一次检索尽可能多的产品元字段,假设通过Shopify api检索的普遍接受的最大记录数是250:

在上面的查询中,我们请求250个产品,对于每一个产品,我们也请求250个相关的元字段值。这一个API调用的结果意味着我们可以有效地一次检索250个产品所需的所有数据,这与REST方法一次只检索一个产品相比是惊人的。

问题来了,当我们运行这个查询,并得到以下API响应:

错误:查询的开销为63252,超过了最大开销1000

发生什么事情了?从Shopify文档

一款应用的成本点数为1000。这意味着查询的总成本不能超过1000点。”

我们的查询比Shopify能提供的要复杂63倍。我们需要化简它。

换句话说,我们需要减少我们要求的记录数量:

  • 250个产品和50个元字段= 13252查询成本,仍然太高。
  • 50个产品和50个元字段= 2652查询成本,越来越接近了。
  • 30个产品和30个元字段= 692查询成本。宾果!

假设我们的商店有30个或更少的元字段,我们可以有效地检索这些值,每次30个产品,而使用REST API,我们一次只能检索一个产品。

你可能还会喜欢:Shopify GraphQL学习工具包

节流

基于此,您可能认为与GraphQL进行数据同步将比REST快30倍,对吧?

不幸的是,事情并没有那么简单。当我们连续快速运行上述查询两次时,例如获得前30个产品,然后是接下来的30个产品,API响应是这样的:

错误:压制

这是因为我们已经用光了1000点桶中的700点,我们必须等待有足够的可用点来提出下一个请求,以每秒50点的速度重新填充。

Shopify文档

“应用程序的成本点为1000个,泄漏率为每秒50个。这意味着在任何给定的时间内,查询的总成本不能超过1000个点,该空间以每秒50个点的速度在应用程序的存储桶中创建。”

如果我们记得使用REST API检索100个产品和400个变体的元字段需要4分钟,让我们比较一下使用上面的GraphQL查询需要多长时间:

正如我们所看到的,尽管GraphQL能够批量检索元字段,但仅检索100个父产品的元字段就需要花费38秒,而且我们仍然需要获得产品变体。

基于上述,我们预计每个GraphQL请求处理30个结果需要14.5秒,而获得所有400个变量需要14个GraphQL请求,因此我们需要额外的203秒。

这意味着即使使用这种方法,仍然需要大约4分钟来检索所有500条记录的元字段,令人失望的是,这与REST API所花费的时间相似。

你可能还会喜欢:GraphQL vs REST:一个Shopify合作伙伴如何提高性能和可靠性

我们的方法

对于我们的应用程序,我们知道给定Shopify商店需要哪些元字段,并且我们有可用的名称空间和键,因此我们可以非常具体地使用我们的方法。

我们发现的最有效的GraphQL查询是只请求这些特定的元字段,并确保只检索我们绝对需要的数据。它看起来是这样的:

pageInfo {hasNextPage}需要知道是否需要从下一页获取更多记录,在这种情况下,我们使用光标字段。legacyResourceId是产品变体的ID,和产品{legacyResourceId}需要将产品变体与其父(即父ID)相关联。

这三个metafields是具体的名称空间:关键我们从这个商店中需要的值。该部分在每个存储中都是动态的,可以根据所需元字段的数量增加或减少。

通过这个查询,我们可以获取我们需要的三个特定的元字段,每次50个产品。

大页面大小vs.小页面大小

由于这种查询成本和限制,我们发现“一次使用更多产品会更快”的常识并不一定正确。

如果页面大小较小,则查询成本较低,因此可以发出更多请求而不受限制。但是,每个请求返回的数据更少。如果页面大小很大,则每次请求都会获得更多数据。但是,查询成本也很高,因此会受到更大的限制。

通过测试从100个产品和400个变体中检索单个元域,我们发现:

  • 每一页产品需要216秒,节流0次
  • 每页5个产品需要44秒,节流0次
  • 每页10个产品需要21秒,节流0次
  • 每页25个产品需要10秒,节流0次
  • 每页50个产品需要10秒,节流三次
  • 每页75个产品需要12秒,节流6次
  • 每页100个产品需要10秒,节流4次
  • 每页150个产品需要16秒,节流7次
  • 每页200个产品需要10秒,节流5次
  • 每页250个产品需要18秒,节流7次

正如你所看到的,计时和油门计数并不完全一致。所花费的总时间是基于三个因素的组合:

  1. 正在检索的元字段的数量
  2. 最佳分页计数
  3. 节气门计数

对于本例,最佳时间是由于所需API请求的最佳数量,因为100个产品和400个变体可以完美地分为25、50、100和200个页数。然而,尽管1、5和10也可以很好地划分到我们的页面计数中,但由于它们低于每个请求检索的产品的最佳阈值,因此速度较慢。

重要的是,我们可以看到,无论每页获取25、50、100还是200个产品,时间都是相同的,这是因为随着页面大小的增加,会有额外的限制。

因此,我们选择每页总是要求25个产品。

结果

总而言之,我们发现在为只需要检索少量产品元字段的存储获取数据时有了巨大的改进,因为GraphQL在这里以低查询成本和非常高效的批量检索而出类拔萃。

对于一个拥有100种产品和400种变体的Shopify商店,每页检索25个结果,我们发现以下数据同步时间与REST API方法相比,如果你还记得的话,它大约需要4分钟(或240秒):

  • 一个元域:~10秒
  • 两个元域:~20秒
  • 5个元字段:~50秒
  • 10个元字段:~100秒
  • 20个元域:~200秒

我们可以看到一个清晰的模式{metafield count * 10}秒出现。

  • 24个元字段:~240秒(与REST API相同)
  • 30个元字段:~300秒(比REST API慢)

对于需要检索超过24个元字段的存储,GraphQL的好处由于限制而丧失了,事实上,REST API更快。因此,我们将根据特定存储所需的元字段数量在REST和GraphQL之间选择正确的方法。

以几个拥有超过10,000种产品和超过10个元域的真实客户商店为例,我们使用GraphQL方法将一个Shopify Standard商店的完整数据同步时间从3小时减少到1小时,将一个类似的Shopify Plus商店的完整数据同步时间从1小时45分钟减少到35分钟。

使用GraphQL批量操作来加快Shopify元字段的检索

我们在GraphQL中发现的改进已经是一个很好的开始,我们仍在深入研究Shopify用于数据检索的其他选项,例如OB欧宝娱乐APPGraphQL批量操作API

这需要一种稍微不同的方法,因为仍然必须使用GraphQL查询。但是,不是直接在响应中接收结果,而是接收一个参考ID,您可以使用它定期检查Shopify是否已经完成了您的数据准备。任务完成后,将为您提供一个用于下载结果的URLJSONL格式。

从我们最初的测试来看,这种方法显示出更好的性能收益。通过使用Shopify批量突变操作,我们已经能够通过一个API调用检索以下数据:

  • 所有产品
  • 所有产品变体
  • 所有产品元域
  • 所有产品变体元场

这有一个查询成本10只拿了30秒才能完成。使用这种方法也不需要担心速率限制、分页或节流,使其成为比REST甚至标准GraphQL调用更高效和性能更好的选项。

通过Shopify合作伙伴计划发展您的业务

了解更多