A space to discuss GraphQL queries, mutations, troubleshooting, throttling, and best practices.
Hi,
I'm trying to query order agreements using the GraphQL admin API, but I'm stuck on how to retrieve additonal pages for the nested "sales" connection within each agreement My initial query to get the agreements, with extraneous fields stripped out, looks something like the following - the section in bold is the nested connection that I need to be able to query for more pages :
query getOrder($id: ID!) { order(id: $id) { agreements(first: 2) { edges { node { id happenedAt sales(first: 5) { edges { node { lineType actionType } } pageInfo { hasNextPage endCursor } } } cursor } pageInfo { hasNextPage endCursor } } } }
Where the outer pagination indicates that there are more agreements to retrieve I can use a similar query, passing in a cursor to get the next page of agreements:
query getMoreAgreements($id: ID!, $cursor: String) { order(id: $id) { agreements(first: 5, after: $cursor) { ... <snip> } } }
What I can't figure out is a way that I can query for a specific OrderAgreement in order that I can then use the appropriate cursor to get the next page of "Sale"s for that agreement.
Could anyone suggest how to achieve this?
Thanks,
Tim
Hi @Timbersson 👋
You should be able to pass the cursor at the root and paginate the nested sales nodes as shown below. The `$c` variable should reflect the `endCursor` on the `firstSale` alias.
query ($id: ID!, $c: String!){
order (id: $id) {
agreements (first: 1) {
nodes {
id
firstSale: sales (first: 1) {
nodes {
id
}
pageInfo {
endCursor #suppose this is "abc123="
hasNextPage
}
}
secondSale: sales (first: 1, after: $c) {
nodes {
id
}
}
}
}
}
}
With variables:
{
"id":"gid://shopify/Order/123456",
"c":"abc123="
}
Hope that helps!
Developer Support @ Shopify
- Was this reply helpful? Click Like to let us know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
Hey @ShopifyDevSup ,
Thanks for the reply, however in my tests that seems to only work for the first agreement in a particular order. Passing in a sales cursor from a subsequent agreement results in an empty list of edges under sales.
To illustrate - lets say I have an order with 2 agreements, and 2 sales nested under each agreement:
"id": "gid://shopify/SalesAgreement/1"
"id": "gid://shopify/Sale/10",
"id": "gid://shopify/Sale/11",
id": "gid://shopify/SalesAgreement/2",
"id": "gid://shopify/Sale/12",
"id": "gid://shopify/Sale/13",
I can query the agreements in in the order, getting the first sale for each agreement something like this:
query firstSales($id: ID!){
order (id: $id) {
agreements (first: 5) {
edges {
node {
id
sales (first: 1) {
edges { node { id } }
pageInfo { hasNextPage endCursor }
}
}
}
}
}
}
For the hypothetical order above, I get back a response as follows:
"order": {
"agreements": {
"edges": [
{
"node": {
"id": "gid://shopify/SalesAgreement/1",
"sales": {
"edges": [{ "node": {"id": "gid://shopify/Sale/10"}}],
"pageInfo": { "hasNextPage": true, "endCursor": "abc123" }
}
}
},
{
"node": {
"id": "gid://shopify/SalesAgreement/2",
"sales": {
"edges": [{"node": {"id": "gid://shopify/Sale/12"}}],
"pageInfo": {"hasNextPage": true, "endCursor": "def456"}}
}
}
]
}
}
So far so good. If I use a query similar to the one suggested, passing in the cursor "abc123" to the sales connection then all is well: I recieve a response that contains information for "gid://shopify/Sale/11".
The problem comes when I pass in cursor "def456" - in this case I get an empty list of sale edges. It seems that the (first:1) on the agreements connection always selects the first agreement, regardless of the cursor that is used further down the query.
Ok, so having experimented with this a little more I have found a kind of work-around solution, though it does not feel very elegant - you need to manage two separate cursors: one to select the agreement, the another for the Sales connection.
The initial query to get the agreements and first sales for each also gets a cursor for each agreement:
query firstSales($id: ID!){
order (id: $id) {
agreements (first: 5) {
edges {
cursor
node {
id
sales (first: 1) {
edges { node { id } }
pageInfo { hasNextPage endCursor }
}
}
}
}
}
}
Resulting in something like this:
"order": {
"agreements": {
"edges": [
{
"cursor": "agreement_cursor_1",
"node": {
"id": "gid://shopify/SalesAgreement/1",
"sales": {
"edges": [{ "node": {"id": "gid://shopify/Sale/10"}}],
"pageInfo": { "hasNextPage": true, "endCursor": "abc123" }
}
}
},
{
"cursor": "agreement_cursor_2",
"node": {
"id": "gid://shopify/SalesAgreement/2",
"sales": {
"edges": [{"node": {"id": "gid://shopify/Sale/12"}}],
"pageInfo": {"hasNextPage": true, "endCursor": "def456"}}
}
}
]
}
}
You can then then pass the cursor of the previous agreement to the one for which you need to read more sales, to a query like this:
query moreSales($id: ID!, $cursor_sale: String!, $cursor_prev_agreement: String){
order (id: $id) {
agreements (first: 1, after:$cursor_prev_agreement) {
edges {
node {
sales (first: 1, after: $cursor_sale) {
edges {
node { id }
}
}
}
}
}
}
}
Calling this query with variables as follows will return the second sale for the second agreement.
{
"id": "order_id",
"cursor_sale": "def456",
"cursor_prev_agreement": "order_agreement_1"
}
It works, but it doesn't smell good 🙁
@ShopifyDevSup is there any chance that SaleAgreement can / will be made to implement "Node" so that they could be queried using the global "node" query? This would allow a much more elegant solution to this problem than the one I've suggested here.
Thanks,
Tim
Absolutely, `SaleAgreement` would definitely be better implemented to extend a `node` interface. Really appreciate you finding a work-around for now, and I'll be sure to share this with the product team!
If you're looking to fetch the universe of `SaleAgreement` nodes, a bulk query may be an option as well:
mutation {
bulkOperationRunQuery(query: "{ orders { edges { node { id agreements { edges { node { id sales { edges { node { id } } } } } } } } } }") {
bulkOperation {
id
status
}
}
}
Developer Support @ Shopify
- Was this reply helpful? Click Like to let us know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
We're running into the same issues.
Thanks for sharing the work around.
@ShopifyDevSup there are has been multiple API release since then an neither SaleAgreement or Sale extend the node interface yet.
Hey @ClementBR , I've taken a look here and I can see that the feedback is currently still submitted with the product team. I don't have an estimate at this time though if this is currently in the roadmap.
I'd be happy to pass on additional feedback if you're able to share a little more information on specifically how this will be beneficial for you beyond what has already been shared. More context is always helpful.
Thanks,
- Kyle G.
Developer Support @ Shopify
- Was this reply helpful? Click Like to let us know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
It would make the pagination issue described above much cleaner and easier.
The work around suggested above by @Timbersson works but it is very convoluted and very inefficient.
It requires keeping track of the previous agreement in the list and then paginating each agreement's sales with a separate query for each agreement
If Agreement implemented the node interface, then we could simply issue a nodes query to paginate multiple agreements' sales with a single query, and without needing to keep track of the previous cursor in the list.
If
Hey @ClementBR , thanks for sharing that. I have passed that additional feedback on for you!
Have a great weekend.
- Kyle G.
Developer Support @ Shopify
- Was this reply helpful? Click Like to let us know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog