From 659d318f7f407e2c6eacc5568692efa37de6e19c Mon Sep 17 00:00:00 2001 From: Jerry Okolo Date: Thu, 11 May 2023 13:57:51 +0100 Subject: [PATCH] Sort by IDs --- website/pages/en/cookbook/sorting.mdx | 348 ++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 website/pages/en/cookbook/sorting.mdx diff --git a/website/pages/en/cookbook/sorting.mdx b/website/pages/en/cookbook/sorting.mdx new file mode 100644 index 000000000000..0eef75056303 --- /dev/null +++ b/website/pages/en/cookbook/sorting.mdx @@ -0,0 +1,348 @@ +--- +title: GraphQL Sorting Strategies +--- + +## Sort by IDs + +When creating subgraphs in The Graph, it's important to use Bytes! as ID for your entities. This can have significant impact on the performance and ease of use of your subgraph. + +Unless for cases like nft traits or unique names where a type ID (which is a string) would be more appropriate. + +If accurate sorting of numerical values is desired, both Strings and Bytes for IDs are not optimal as the sorting is done non-sequentially which can lead to unexpected results. If attempting to sort by id of type "ID" (which is a string), the ordered sequence might look like this: + +schema.graphql: + +```graphql +type Transfer @entity { + id: ID! + from: Bytes! # address + to: Bytes! # address + tokenId: BigInt! # uint256 +} +``` + +Query: + +```graphql +{ + transfers(first: 5, orderBy: id) { + id + tokenId + } +} +``` + +Query Response: + +```json +{ + "data": { + "transfers": [ + { + "id": "1", + "tokenId": "1" + }, + { + "id": "10", + "tokenId": "10" + }, + { + "id": "100", + "tokenId": "100" + }, + { + "id": "101", + "tokenId": "101" + }, + { + "id": "102", + "tokenId": "102" + } + ] + } +} +``` + +If attempting to sort you IDs that are Bytes, the ordered sequence might look like this: + +schema.graphql: + +```graphql +type Transfer @entity { + id: Bytes! + from: Bytes! # address + to: Bytes! # address + tokenId: BigInt! # uint256 +} +``` + +Query: + +```graphql +{ + transfers(first: 5, orderBy: id) { + id + tokenId + } +} +``` + +Query Response: + +```json +{ + "data": { + "transfers": [ + { + "id": "0x00010000", + "tokenId": "256" + }, + { + "id": "0x00020000", + "tokenId": "512" + }, + { + "id": "0x01000000", + "tokenId": "1" + }, + { + "id": "0x01010000", + "tokenId": "257" + }, + { + "id": "0x01020000", + "tokenId": "513" + } + ] + } +} +``` + +## Ideal Sorting for Numerical Values + +To improve the sorting, creating another property on the entity that is a BigInt (in this example it is tokenId) will allow for sorting to be optimized sequentially. + +```graphql +type Transfer @entity { + id: Bytes! + from: Bytes! # address + to: Bytes! # address + tokenId: BigInt! # uint256 +} +``` + +Query: + +```graphql +{ + transfers(first: 5, orderBy: tokenId) { + id + tokenId + } +} +``` + +Query Response: + +```json +{ + "data": { + "transfers": [ + { + "id": "1", + "tokenId": "1" + }, + { + "id": "2", + "tokenId": "2" + }, + { + "id": "3", + "tokenId": "3" + }, + { + "id": "4", + "tokenId": "4" + }, + { + "id": "5", + "tokenId": "5" + } + ] + } +} +``` +--- +title: GraphQL Sorting Strategies +--- + +## Sort by IDs + +When creating subgraphs in The Graph, it's important to use Bytes! as ID for your entities. This can have significant impact on the performance and ease of use of your subgraph. + +Unless for cases like nft traits or unique names where a type ID (which is a string) would be more appropriate. + +If accurate sorting of numerical values is desired, both Strings and Bytes for IDs are not optimal as the sorting is done non-sequentially which can lead to unexpected results. If attempting to sort by id of type "ID" (which is a string), the ordered sequence might look like this: + +schema.graphql: + +```graphql +type Transfer @entity { + id: ID! + from: Bytes! # address + to: Bytes! # address + tokenId: BigInt! # uint256 +} +``` + +Query: + +```graphql +{ + transfers(first: 5, orderBy: id) { + id + tokenId + } +} +``` + +Query Response: + +```json +{ + "data": { + "transfers": [ + { + "id": "1", + "tokenId": "1" + }, + { + "id": "10", + "tokenId": "10" + }, + { + "id": "100", + "tokenId": "100" + }, + { + "id": "101", + "tokenId": "101" + }, + { + "id": "102", + "tokenId": "102" + } + ] + } +} +``` + +If attempting to sort you IDs that are Bytes, the ordered sequence might look like this: + +schema.graphql: + +```graphql +type Transfer @entity { + id: Bytes! + from: Bytes! # address + to: Bytes! # address + tokenId: BigInt! # uint256 +} +``` + +Query: + +```graphql +{ + transfers(first: 5, orderBy: id) { + id + tokenId + } +} +``` + +Query Response: + +```json +{ + "data": { + "transfers": [ + { + "id": "0x00010000", + "tokenId": "256" + }, + { + "id": "0x00020000", + "tokenId": "512" + }, + { + "id": "0x01000000", + "tokenId": "1" + }, + { + "id": "0x01010000", + "tokenId": "257" + }, + { + "id": "0x01020000", + "tokenId": "513" + } + ] + } +} +``` + +## Ideal Sorting for Numerical Values + +To improve the sorting, creating another property on the entity that is a BigInt (in this example it is tokenId) will allow for sorting to be optimized sequentially. + +```graphql +type Transfer @entity { + id: Bytes! + from: Bytes! # address + to: Bytes! # address + tokenId: BigInt! # uint256 +} +``` + +Query: + +```graphql +{ + transfers(first: 5, orderBy: tokenId) { + id + tokenId + } +} +``` + +Query Response: + +```json +{ + "data": { + "transfers": [ + { + "id": "1", + "tokenId": "1" + }, + { + "id": "2", + "tokenId": "2" + }, + { + "id": "3", + "tokenId": "3" + }, + { + "id": "4", + "tokenId": "4" + }, + { + "id": "5", + "tokenId": "5" + } + ] + } +} +```