Subgraph Development, del 2: Håndtering av arrays og identifisering av enheter

(ProtoFire.io)

(Del 1 ) | Del 2

Dette blogginnlegget gir praktiske anbefalinger om hvordan du bruker arrays effektivt og genererer enhets-ID-er som er unike og refererer til.

I del 1 av denne serien ga vi en oversikt over underbilder for å hjelpe utviklere å forstå deres grunnleggende struktur. I tillegg delte vi også vår innsikt for kartlegging og aggregering av data.

Denne gangen vil vi diskutere to andre emner: håndtering av matriser og generering av ID-er for enheter som både er unike og lett refererte til. Som en del av diskusjonen vil vi gi våre anbefalinger om hvordan du effektivt kan administrere matriser og riktig navngi enheter.

Håndtere matriser effektivt

Å legge til matriser i enheter er nyttig i visse scenarier. For eksempel er det tilfeller der vi trenger å modellere en liste over adresser for en datakilde eller spore historiske endringer for et bestemt felt over tid.

Uten forkunnskap om hvordan matriser fungerer i underbilder, kan vi vurdere opprette et felt av en matritype på en enhetstypedefinisjon (i schema.graphql -filen) og initialisere en tom matrise hver gang en ny enhet av samme type opprettes. Når nye data legges til i matrisen, kan vi skyve dataene og lagre enheten. Selv om dette høres intuitivt ut, fungerer det dessverre ikke.

Manuell håndtering av matriser på underbilder, spesielt i scenariet ovenfor, har noen få forbehold. Når du får tilgang til en matrise av en enhet, er det du faktisk får en kopi av matrisen. Dermed, hvis du legger til nye data og lagrer enheten, vil det ikke fungere som du forventer, siden du bare endrer en kopi av matrisen, mens originalen blir uendret.

For å oppdatere selve matrisen, kan vi plassere kopien av matrisen i en variabel og deretter endre dataene. Deretter kan vi sette variabelen som den nye matrisen på enheten. På denne måten erstattes den gamle matrisen med kopien. Denne prosessen med å oppdatere matrisen er eksemplifisert i følgende kode.

// This won"t work
entity.numbers.push(BigInt.fromI32(1))
entity.save()// This will work
let numbers = entity.numbers
numbers.push(BigInt.fromI32(1))
entity.numbers = numbers
entity.save()

Mens du kan oppdatere en matrise på den måten som er vist ovenfor, er det ikke en ideell løsning . Foruten å være upraktisk, er det en annen grunn til ikke å håndtere matriser manuelt – tidsreiser. (Les del 1 av serien for å lære mer om tidsreiser.)

Det er bare mulig å utføre tidsreiser, fordi underbilder holder oversikt over alle endringene i alle enhetene som presenterer alle tid. Hvis det er mange enheter med matrixfelt, som er store og ofte oppdateres, må kopier av alle matriser også lagres. Dette vil ta en toll på ytelsen og diskplassen til indekserer som indekserer underbildet ditt.

For tiden er The Graphs vertte tjeneste den eneste tilgjengelige indeksereren som er tilgjengelig. I fremtiden kan flere indeksører bli med i tillegg til The Graphs desentraliserte nettverk. Disse nye indekseringene vil kunne velge hvilke underbilder som skal indekseres. Hvis underbildet ditt er dårlig optimalisert på grunn av matriser, vil det sannsynligvis ikke bli hentet av noen indekserer.

For å optimalisere matriser kan vi bruke @derivedFrom kommentar. Denne metoden gjør det mulig å fylle ethvert arrayfelt definert i en enhetstype automatisk av alle enheter av den spesifiserte typen knyttet til enheten vi definerer. Følgende eksempel skildrer bruken av @derivedFrom merknaden.

type User @entity {
id: ID! positions: [Position!]! @derivedFrom(field: “user”)
}type Position @entity {
id: ID! user: User! # This is the ID String of the User
}

I eksemplet ovenfor har vi en bruker med en automatisk generert liste over Position enhetene. Hver gang underbildet vårt mottar et spørsmål som ber om posisjonsfeltet til User -enheten, utfører undergrafen en omvendt oppslag for alle Position -typenheter knyttet til det spesifikke User -enheten i user -feltet. På denne måten er de tilknyttede enhetene de som har streng-ID for andre enheter i et av feltene.

Ved å bruke @derivedFrom -kommentaren kan vi definere enheten skriv inn det vi ønsker for matrisedataene våre, definer feltet som brukes når matrisen hentes, og koble det til den opprinnelige enheten via ID-en. Det er også fordelen med å kunne legge til flere data (f.eks. Opprette eller oppdatere metadata) til enhetene som representerer matardataene. Siden dette er fullverdige enheter, kan vi enkelt oppdatere dem ved å laste inn ID-ene deres i stedet for å slå dem opp i matrisen.

Mens vi håndterer arrays med @derivedFrom -kommentar er enklere, er det fortsatt noen hensyn å være klar over.For det første vil det bare fungere med en-til-mange relasjoner. I mange til mange forhold trenger vi fremdeles den ene siden av ligningen for å håndtere matrisen manuelt. For det andre vil du ikke kunne få tilgang til matardataene mens undergrafen indekseres, siden matrisen er fylt ut når du blir spurt.

Opprette en navngivning konvensjon for enhets-ID

Alle enhetene som er definert i schema.graphql -filen identifiseres av et ID-felt som er erklært som en ID! type representert som en streng. ID-feltet er viktig ettersom det brukes til å laste inn, opprette og lagre enheter.

Siden ID-feltet er det primære middel for å identifisere en enhet, bør det alltid være unikt. Når det er sagt, er det ikke vanskelig å garantere det unike med en ID. Data som er til stede under indekseringstid kan kombineres for å generere unike IDer. Følgende kode er et eksempel på dette.

event.transaction.hash.toHex() + "-" + 
event.logIndex.toString()

Ved å ta transaksjonshashen for en hendelse (unik for forskjellige transaksjoner) og legge den til loggindeksen for den spesielle hendelsen (som identifiserer en hendelse i en transaksjon), kan vi generere en unik sammensatt ID. På denne måten kan vi identifisere en bestemt enhet blant andre enheter av samme type forutsatt at det bare opprettes en enkelt enhet for en enkelt hendelse. Om nødvendig kan vi også legge til flere data for å identifisere et hvilket som helst antall enheter som er opprettet i samme hendelse. For eksempel kan vi sette en teller for hver gang en enhet opprettes og legge til verdien til den nylig opprettede enheten.

Selv om det er praktisk å ha en enkel metode for å generere unike ID-er for enhetene våre, bør vi også streber etter å generere ID-er som er forutsigbare og kan refereres til. Hvis vi har enheter relatert til en del av domenet vårt som sannsynligvis vil bli spurt av sluttbrukere via deres ID, kan vi generere en ID som refererer til domenet vi jobber med.

Som et eksempel kan du vurdere et scenario hvor vi oppretter en Account -enhet på en DEX-undergraf. Denne Account enheten lagrer brukerens saldo, samt annen informasjon. Hvis vi oppretter enhets-ID basert på transaksjonshashen, kan brukeren søke etter transaksjonen som opprettet den i utgangspunktet og gjenskape den, men den vil ikke være intuitiv. Et bedre alternativ ville være å opprette en ID basert på brukerens Ethereum-adresse, og om nødvendig kombinere den med noe annet relevant for domenet. På denne måten kan vi unikt identifisere en bestemt brukerkonto fra andre kontoer til samme bruker.

Oppsummert kan generiske unike ID-er uten domenespesifikke data være nyttige for enheter som ikke vil bli oppdatert kontinuerlig. Dette er ideelt for enheter som er opprettet for å lagre metadata for domenespesifikke hendelser som vil bli konsumert fra en avledet matrise på en hovedenhet. For eksempel er generiske unike ID-er bedre egnet for overføringer, mynter, forbrenninger og bytter.

På den annen side er domenespesifikke ID-er ideelle for hovedenheter og andre enheter som vil få hyppige oppdateringer. Du bruker sannsynligvis en kombinasjon av en Ethereum-adresse og noen andre domenespesifikke ID-er. I de fleste tilfeller vil en smart kontrakt generere unike IDer og logge dem på hendelsene. Hvis dette ikke er tilfelle, må du studere den smarte kontrakten og identifisere hva som gjør enheten din unik og bruke disse dataene til å generere en ID.

Som en sidemerknad, toHex() og toHexString() metoder – ofte brukt til å generere IDer fra adresser eller hashes – returnerer en liten bokstav. Dette betyr at når du spør etter et undergrafi for enheter, bør ID-strengen som er oppgitt med små bokstaver, ettersom spørringen er mellom store og små bokstaver.

Hvis du vil ha mer informasjon om utvikling av subgraf, kan du sjekke ut grafens offisiell dokumentasjon . Ytterligere detaljer finner du også i prosjektets GitHub-arkiv . Grafen har også et aktivt og voksende samfunn som er klar til å hjelpe og svare på spørsmålene som oppstår. Vi oppfordrer alle som er interessert i å utvikle sine egne underbilder, til å bli med på Graph’s Discord-server .

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *