10 मिनट
Querying Best Practices
The Graph ब्लॉकचेन से डेटा क्वेरी करने का एक विकेन्द्रीकृत तरीका प्रदान करता है। इसका डेटा एक GraphQL API के माध्यम से एक्सपोज़ किया जाता है, जिससे इसे GraphQL भाषा के साथ क्वेरी करना आसान हो जाता है।
GraphQL भाषा के आवश्यक नियम और Best Practices सीखें ताकि आप अपने Subgraph को optimize कर सकें।
ग्राफ़कॉल एपीआई को क्वेरी करना
GraphQL Query की संरचना
REST API के विपरीत, एक रेखांकन API एक स्कीमा पर बनाया गया है जो परिभाषित करता है कि कौन से प्रश्न किए जा सकते हैं।
उदाहरण के लिए, token
क्वेरी का उपयोग करके एक टोकन प्राप्त करने के लिए की गई क्वेरी इस प्रकार होगी:
1query GetToken($id: ID!) {2 token(id: $id) {3 id4 owner5 }6}
जो निम्नलिखित पूर्वानुमानित JSON प्रतिक्रिया लौटाएगा (जब उचित $id
variable value_ पास किया जाएगा):
1{2 "token": {3 "id": "...",4 "owner": "..."5 }6}
GraphQL क्वेरीज़ GraphQL भाषा का उपयोग करती हैं, जो कि एक स्पेसिफिकेशन पर परिभाषित है।
उपरोक्त GetToken
क्वेरी कई भाषाओं के भागों से बनी है (नीचे [...]
प्लेसहोल्डर के साथ प्रतिस्थापित):
1query [operationName]([variableName]: [variableType]) {2 [queryName]([argumentName]: [variableName]) {3 # "{ ... }" express a Selection-Set, we are querying fields from `queryName`.4 [field]5 [field]6 }7}
GraphQL क्वेरी लिखने के नियम
- प्रत्येक
queryName
को प्रत्येक ऑपरेशन में केवल एक बार ही उपयोग किया जाना चाहिए। - प्रत्येक
field
का चयन में केवल एक बार ही उपयोग किया जा सकता है (हमtoken
के अंतर्गत id को दो बार क्वेरी नहीं कर सकते)। - कुछ field या क्वेरी (जैसे tokens) जटिल प्रकार के परिणाम लौटाते हैं, जिनके लिए उप-फ़ील्ड का चयन आवश्यक होता है। जब अपेक्षित हो तब चयन न देना (या जब अपेक्षित न हो - उदाहरण के लिए, id पर चयन देना) एक त्रुटि उत्पन्न करेगा। किसी फ़ील्ड के प्रकार को जानने के लिए, कृपया Graph Explorer देखें।
- किसी तर्क को असाइन किया गया कोई भी चर उसके प्रकार से मेल खाना चाहिए।
- चरों की दी गई सूची में, उनमें से प्रत्येक अद्वितीय होना चाहिए।
- सभी परिभाषित चर का उपयोग किया जाना चाहिए।
ध्यान दें: इन नियमों का पालन न करने पर The Graph API से त्रुटि होगी।
पूरी नियमों की सूची और कोड उदाहरणों के लिए GraphQL Validations guide देखें: (https://thegraph.com/resources/migration-guides/graphql-validations-migration-guide/)
एक ग्राफ़क्यूएल एपीआई के लिए एक प्रश्न भेजना
GraphQL एक भाषा और प्रथाओं का सेट है जो HTTP के माध्यम से संचालित होता है।
इसका मतलब है कि आप एक GraphQL API को मानक fetch
(स्थानीय रूप से या @whatwg-node/fetch
या isomorphic-fetch
के माध्यम से) का उपयोग करके क्वेरी कर सकते हैं।
हालांकि, जैसा कि “Querying from an Application” में उल्लेख किया गया है, यह अनुशंसित है कि graph-client
का उपयोग किया जाए, जो निम्नलिखित अद्वितीय विशेषताओं का समर्थन करता है:
- Cross-chain Subgraph Handling: एक ही query में multiple Subgraphs से data प्राप्त करना
- स्वचालित ब्लॉक ट्रैकिंग
- स्वचालित Pagination
- पूरी तरह से टाइप किया गया परिणाम
The Graph के साथ graph-client
का उपयोग करके क्वेरी करने का तरीका:
1import { execute } from '../.graphclient'23const query = `4query GetToken($id: ID!) {5 token(id: $id) {6 id7 owner8 }9}10`11const variables = { id: '1' }1213async function main() {14 const result = await execute(query, variables)15 // `result` is fully typed!16 console.log(result)17}1819main()
More GraphQL क्लाइंट विकल्पों को “Querying from an Application” में कवर किया गया है।
Best Practices
हमेशा स्टैटिक क्वेश्चन लिखें
एक सामान्य (खराब) प्रथा है कि क्वेरी स्ट्रिंग्स को निम्नलिखित तरीके से गतिशील रूप से बनाया जाए:
1const id = params.id2const fields = ['id', 'owner']3const query = `4query GetToken {5 token(id: ${id}) {6 ${fields.join('\n')}7 }8}9`
जबकि उपरोक्त स्निपेट एक मान्य GraphQL क्वेरी उत्पन्न करता है, इसमें कई कमियाँ हैं:
- यह संपूर्ण क्वेरी को समझना और कठिन बना देता है।
- डेवलपर्स स्ट्रिंग इंटरपोलेशन को सुरक्षित रूप से सैनिटाइज़ करने के लिए जिम्मेदार होते हैं
- रिक्वेस्ट पैरामीटर्स के रूप में वेरिएबल्स के मान न भेजने से सर्वर-साइड पर संभावित कैशिंग को रोका जा सकता है
- यह टूल्स को क्वेरी का स्टैटिक रूप से विश्लेषण करने से रोकता है (उदाहरण: Linter या टाइप जेनरेशन टूल्स)
इसी कारण, यह अनुशंसा की जाती है कि हमेशा क्वेरीज़ को स्थिर स्ट्रिंग्स के रूप में लिखा जाए।
1import { execute } from 'your-favorite-graphql-client'23const id = params.id4const query = `5query GetToken($id: ID!) {6 token(id: $id) {7 id8 owner9 }10}11`1213const result = await execute(query, {14 variables: {15 id,16 },17})
ऐसा करने से कई लाभ होते हैं:
- आसानी से पढ़ने और बनाए रखने योग्य क्वेरीज़
- GraphQL सर्वर वेरिएबल्स की स्वच्छता को संभालता है
- वेरिएबल्स को सर्वर-स्तर पर कैश किया जा सकता है
- क्वेरीज़ को उपकरणों द्वारा स्थिर रूप से विश्लेषण किया जा सकता है (अधिक जानकारी निम्नलिखित अनुभागों में) -
स्टेटिक क्वेरीज़ में फ़ील्ड्स को शर्तानुसार कैसे शामिल करें
आप owner
फ़ील्ड को केवल एक विशेष शर्त पर शामिल करना चाह सकते हैं।
आप इसके लिए @include(if:...)
निर्देश का उपयोग कर सकते हैं जैसे कि निम्नलिखित:
1import { execute } from 'your-favorite-graphql-client'23const id = params.id4const query = `5query GetToken($id: ID!, $includeOwner: Boolean) {6 token(id: $id) {7 id8 owner @include(if: $includeOwner)9 }10}11`1213const result = await execute(query, {14 variables: {15 id,16 includeOwner: true,17 },18})
नोट: विपरीत निर्देश @skip(if: ...)
है।
आप जो चाहते हैं वह मांगें
GraphQL अपने “Ask for what you want” टैगलाइन के लिए प्रसिद्ध हुआ।
इस कारण, GraphQL में सभी उपलब्ध फ़ील्ड्स को बिना उन्हें व्यक्तिगत रूप से सूचीबद्ध किए प्राप्त करने का कोई तरीका नहीं है।
- GraphQL APIs query करते समय, हमेशा वो fields की query करने की सोचें जो वास्तव में use होंगे।
- सुनिश्चित करें कि क्वेरीज़ केवल उतने ही एंटिटीज़ लाएँ जितनी आपको वास्तव में आवश्यकता है। डिफ़ॉल्ट रूप से, क्वेरीज़ एक संग्रह में 100 एंटिटीज़ लाएँगी, जो आमतौर पर उपयोग में लाई जाने वाली मात्रा से अधिक होती है, जैसे कि उपयोगकर्ता को प्रदर्शित करने के लिए। यह न केवल एक क्वेरी में शीर्ष-स्तरीय संग्रहों पर लागू होता है, बल्कि एंटिटीज़ के नेस्टेड संग्रहों पर भी अधिक लागू होता है।
उदाहरण के लिए, निम्नलिखित क्वेरी में:
1query listTokens {2 tokens {3 # will fetch up to 100 tokens4 id5 transactions {6 # will fetch up to 100 transactions7 id8 }9 }10}
प्रतिक्रिया में प्रत्येक 100 टोकनों के लिए 100 लेन-देन(transaction) हो सकते हैं।
यदि application को केवल 10 लेन-देन(transaction) की आवश्यकता है, तो क्वेरी को लेनदेन फ़ील्ड पर स्पष्ट रूप से first: 10 सेट करना चाहिए।
एक ही क्वेरी का उपयोग करके कई रिकॉर्ड्स का अनुरोध करें
डिफ़ॉल्ट रूप से, Subgraphs में एक record के लिए singular entity होती है। कई records प्राप्त करने के लिए, plural entities और filter का उपयोग करें: where: {id_in:[X,Y,Z]}
या where: {volume_gt:100000}
अप्रभावी क्वेरी करने का उदाहरण:
1query SingleRecord {2 entity(id: X) {3 id4 name5 }6}7query SingleRecord {8 entity(id: Y) {9 id10 name11 }12}
इष्टतम क्वेरी करने का उदाहरण:
1query ManyRecords {2 entities(where: { id_in: [X, Y] }) {3 id4 name5 }6}
एकल अनुरोध में कई क्वेरियों को संयोजित करें।
आपका application निम्नलिखित प्रकार के डेटा को क्वेरी करने की आवश्यकता हो सकती है: -
1import { execute } from "your-favorite-graphql-client"23const tokensQuery = `4query GetTokens {5 tokens(first: 50) {6 id7 owner8 }9}10`11const countersQuery = `12query GetCounters {13 counters {14 id15 value16 }17}18`1920const [tokens, counters] = Promise.all(21 [22 tokensQuery,23 countersQuery,24 ].map(execute)25)
जबकि यह कार्यान्वयन पूरी तरह से मान्य है, यह GraphQL API के साथ दो राउंड ट्रिप की आवश्यकता होगी।
सौभाग्य से, एक ही GraphQL अनुरोध में कई क्वेरी भेजना भी मान्य है, जैसा कि नीचे दिया गया है:
1import { execute } from "your-favorite-graphql-client"23const query = `4query GetTokensandCounters {5 tokens(first: 50) {6 id7 owner8 }9 counters {10 id11 value12 }13}14`1516const { result: { tokens, counters } } = execute(query)
यह तरीका कुल मिलाकर प्रदर्शन में सुधार करेगा क्योंकि यह नेटवर्क पर बिताया गया समय कम करेगा (API के लिए एक राउंड ट्रिप बचाता है) और एक अधिक संक्षिप्त कार्यान्वयन प्रदान करेगा।
लीवरेज ग्राफक्यूएल फ़्रैगमेंट
GraphQL क्वेरी लिखने में सहायक एक सुविधा है GraphQL Fragment।
निम्नलिखित क्वेरी को देखने पर, आप देखेंगे कि कुछ फ़ील्ड्स कई चयन-सेट्स ({ ... }
) में दोहराए गए हैं:
1query {2 bondEvents {3 id4 newDelegate {5 id6 active7 status8 }9 oldDelegate {10 id11 active12 status13 }14 }15}
ऐसे दोहराए गए फ़ील्ड (id, active, status) कई समस्याएँ लाते हैं:
- बड़ी क्वेरीज़ पढ़ने में कठिन होती हैं।
- जब ऐसे टूल्स का उपयोग किया जाता है जो क्वेरी के आधार पर TypeScript टाइप्स उत्पन्न करते हैं (इस पर अंतिम अनुभाग में और अधिक), newDelegate और oldDelegate दो अलग-अलग इनलाइन इंटरफेस के रूप में परिणत होंगे।
एक पुनर्गठित संस्करण का प्रश्न निम्नलिखित होगा:
1query {2 bondEvents {3 id4 newDelegate {5 ...DelegateItem6 }7 oldDelegate {8 ...DelegateItem9 }10 }11}1213# we define a fragment (subtype) on Transcoder14# to factorize repeated fields in the query15fragment DelegateItem on Transcoder {16 id17 active18 status19}
GraphQL में fragment का उपयोग पढ़ने की सुविधा बढ़ाएगा (विशेष रूप से बड़े स्तर पर) और बेहतर TypeScript प्रकारों की पीढ़ी का परिणाम देगा।
जब टाइप्स जेनरेशन टूल का उपयोग किया जाता है, तो उपरोक्त क्वेरी एक सही ‘DelegateItemFragment’ टाइप उत्पन्न करेगी (अंतिम “Tools” अनुभाग देखें)।
ग्राफकॉल फ्रैगमेंट क्या करें और क्या न करें
Fragment base must be a type
एक फ़्रैगमेंट गैर-लागू प्रकार पर आधारित नहीं हो सकता, संक्षेप में, ऐसे प्रकार पर जिसमें फ़ील्ड नहीं होते हैं।
1fragment MyFragment on BigInt {2 # ...3}
BigInt एक स्केलर (मूल “plain” type) है जिसे किसी फ़्रैगमेंट के आधार के रूप में उपयोग नहीं किया जा सकता।
How to spread a Fragment
फ्रैगमेंट विशिष्ट प्रकारों पर परिभाषित किए जाते हैं और उन्हें क्वेरी में उपयुक्त रूप से उपयोग किया जाना चाहिए।
उदाहरण:
1query {2 bondEvents {3 id4 newDelegate {5 ...VoteItem # Error! `VoteItem` cannot be spread on `Transcoder` type6 }7 oldDelegate {8 ...VoteItem9 }10 }11}1213fragment VoteItem on Vote {14 id15 voter16}
newDelegate
और oldDelegate
प्रकार के Transcoder
हैं।
यहाँ Vote
प्रकार के एक खंड को फैलाना संभव नहीं है।
Fragment को data की एक atomic business unit के रूप में define करें।
GraphQL Fragments
को उनके उपयोग के आधार पर परिभाषित किया जाना चाहिए।
अधिकांश उपयोग मामलों के लिए, एक प्रकार पर एक फ़्रैगमेंट परिभाषित करना (दोहराए गए फ़ील्ड उपयोग या प्रकार निर्माण के मामले में) पर्याप्त होता है।
यहाँ एक सामान्य नियम है फ्रैगमेंट्स का उपयोग करने के लिए:
- जब समान प्रकार के फ़ील्ड किसी क्वेरी में दोहराए जाते हैं, तो उन्हें
Fragment
में समूहित करें। - जब समान लेकिन भिन्न फ़ील्ड्स को दोहराया जाता है, तो कई फ़्रैगमेंट्स बनाएं, उदाहरण के लिए:
1# base fragment (mostly used in listing)2fragment Voter on Vote {3 id4 voter5}67# extended fragment (when querying a detailed view of a vote)8fragment VoteWithPoll on Vote {9 id10 voter11 choiceID12 poll {13 id14 proposal15 }16}
मूलभूत उपकरण
ग्राफक्यूएल वेब-आधारित खोजकर्ता
क्वेरीज़ को अपने application में चलाकर उनका पुनरावर्तन करना कठिन हो सकता है। इसी कारण, अपनी क्वेरीज़ को अपने application में जोड़ने से पहले उनका परीक्षण करने के लिए बिना किसी संकोच के Graph Explorer का उपयोग करें। Graph Explorer आपको एक पूर्व-कॉन्फ़िगर किया हुआ GraphQL प्लेग्राउंड प्रदान करेगा, जहाँ आप अपनी क्वेरीज़ का परीक्षण कर सकते हैं।
यदि आप अपनी क्वेरीज़ को डिबग/परखने के लिए एक अधिक लचीला तरीका ढूंढ रहे हैं, तो अन्य समान वेब-आधारित टूल उपलब्ध हैं जैसे Altair और GraphiQL
ग्राफक्यूएल लाइनिंग
उपरोक्त सर्वोत्तम प्रथाओं और वाक्य रचना नियमों का पालन करने के लिए, निम्नलिखित वर्कफ़्लो और IDE टूल्स का उपयोग करना अत्यधिक अनुशंसित है।
GraphQL ESLint
GraphQL ESLint आपकी बिना किसी अतिरिक्त प्रयास के GraphQL सर्वोत्तम प्रथाओं का पालन करने में मदद करेगा।
“operations-recommended” कॉन्फ़िगरेशन सेटअप करने से आवश्यक नियम लागू होंगे जैसे:-
@graphql-eslint/fields-on-correct-type
: क्या कोई फ़ील्ड सही प्रकार पर उपयोग की गई है?@graphql-eslint/no-unused variables
: क्या दिया गया चर अनुपयोगी रहना चाहिए?- और अधिक!
यह आपको बिना प्लेग्राउंड पर क्वेरी का परीक्षण किए या उन्हें प्रोडक्शन में चलाए बिना ही त्रुटियों को पकड़ने की अनुमति देगा!
आईडीई प्लगइन्स
VSCode और GraphQL
GraphQL VSCode extension आपके विकास वर्कफ़्लो में एक बेहतरीन जोड़ है जिससे आपको यह प्राप्त होता है:
- सिंटैक्स हाइलाइटिंग
- ऑटो-कंप्लीट सुझाव
- स्कीमा के खिलाफ मान्यता
- निबंध
- फ्रैगमेंट्स और इनपुट टाइप्स के लिए परिभाषा पर जाएं।
यदि आप graphql-eslint का उपयोग कर रहे हैं, तो ESLint VSCode एक्सटेंशन आपके कोड में त्रुटियों और चेतावनियों को इनलाइन सही तरीके से देखने के लिए आवश्यक है।
WebStorm/Intellij और GraphQL
JS GraphQL प्लगइन आपके GraphQL के साथ काम करने के अनुभव को काफी बेहतर बनाएगा, जिससे आपको निम्नलिखित सुविधाएँ मिलेंगी:
- सिंटैक्स हाइलाइटिंग
- ऑटो-कंप्लीट सुझाव
- स्कीमा के खिलाफ मान्यता
- निबंध
इस विषय पर अधिक जानकारी के लिए, WebStorm लेख देखें, जिसमें इस प्लगइन की सभी प्रमुख विशेषताओं को प्रदर्शित किया गया है।