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" + } + ] + } +} +```