Skrive data til Cloud Firestore

Forskjellen på relasjonsdatabaser og dokumentbaserte databaser
Tidligere har du kanskje lært å modellere relasjonsdatabaser og å kode dem i SQL. En viktig forskjell på relasjonsdatabaser (SQL-baserte databaser) og dokumentbaserte databaser (NoSQL-databaser) er at i dokumentbaserte databaser er det ingen forhåndsbestemte regler for hvordan databasen skal bygges opp. Hele databasen tar utgangspunkt i ei tekstfil (ofte ei .JSON-fil) der vi legger all dataene inn, uten å ha bestemt felt, rader og kolonner på forhånd. Vi skriver rett og slett bare all dataene inn i tekstfila. Dette gjør dokumentbaserte databaser veldig fleksible og enkle å sette opp, men det krever også mer orden fra dem som skal bruke databasen. For at en slik database skal være brukervennlig, krever det dessuten at programmet eller nettsiden vi bruker til å få tilgang til databasen, er satt opp på en måte som gjør det enklere å legge inn riktig data.
Vi kan likevel trekke ut noen likheter mellom relasjonsdatabaser (SQL) og dokumentbaserte databaser (NoSQL). En tabell i SQL tilsvarer ei samling (collection) i NoSQL, og en rad (all dataene tilknyttet et objekt i databasen) i SQL tilsvarer et dokument (document) i NoSQL. Du kan lese mer om oppbyggingen av dokumentbaserte databaser på MongoDBs side "What is a Document Database".
Trenger vi datamodellering med dokumentbaserte databaser?
Det kan kanskje være enkelt å tro at vi ikke trenger datamodellering i NoSQL-databaser, siden vi ikke trenger å opprette tabeller og felt på samme måte som i SQL, men det kan uansett være en god idé å ha oversikt over hvordan dataene skal organiseres i databasen. Derfor kan det være lurt å sette opp en datamodell også når du skal bruke NoSQL-databaser.
På bildet under ser du oppbyggingen av en Firestore-database med elevdata:

Som du kan se på bildene, har noen av elevene ulik info. Noen har telefon, andre har e-post, og noen har begge deler. Dette ville ikke ha vært mulig i en SQL-database, der alle feltene må være opprettet på forhånd. Dette viser noe av fleksibiliteten i en NoSQL-database.
Legge inn data i databasen
Du skal nå legge inn dataene fra bildet over i Firebase-databasen din. Åpne HTML-fila index.html som du opprettet i forrige leksjon. Scriptet i index.html skal se omtrent slik ut:
1<script type="module"> 2 // Importerer intitalizApp fra Firebase-app SDK 3 import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-app.js"; 4 // Importerer alle Firestore-funksjonene vi skal bruke 5 // Om du får feilmeldinga "ReferenceError: [...] is not defined", kan det være det fordi du har brukt en Firestore-funksjon uten å ha importert den her. 6 import { getFirestore } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js" 7 8 // Konfigurerer Firebase 9 const firebaseConfig = { 10 apiKey: "_API_KEY_", 11 authDomain: "_PROJECT_ID_.firebaseapp.com", 12 projectId: "_PROJECT_ID_", 13 storageBucket: "_PROJECT_ID_.appspot.com", 14 messagingSenderId: "_SENDER_ID_", 15 appId: "_APP_ID_", 16 }; 17 18 // Starter opp Firebase med den angitte konfigurasjonen 19 const app = initializeApp(firebaseConfig); 20 // Henter ut referanse til Firestore-databasen 21 const db = getFirestore(); 22</script>
Opprette et nytt dokument i databasen
Du skal nå skrive kode for å opprette et nytt dokument i databasen. Den enkleste måten å gjøre dette på er å bruke Firestore-funksjonene addDoc() og collection(). Dokumenter som opprettes med addDoc() får automatisk en unik ID, så du trenger ikke tenke på at dokumentet må ha en primærnøkkel.
En viktig ting med funksjonene som er knyttet til Firestore, er at de er asynkrone. Det vil si at når en databaseoperasjon skal kjøre, vil programmet fortsette å kjøre neste kodelinje uten å vente på at kommunikasjonen med databasen er fullført. Derfor skriver vi ordet await foran disse funksjonene, slik at programmet venter til kommunikasjonen med databasen er fullført før neste kodelinje kjøres.
addDoc() er en funksjon for å skrive data til databasen. Denne funksjonen tar inn to parametere: hvilken samling (collection) dataene skal skrives til, og hvilken data som skal skrives, slik:
addDoc(_COLLECTION_, _DATA_);
Dataene skrives inn på formen
{
_FELTNAVN_1_: "_DATA_1_",
_FELTNAVN_2_: "_DATA_2_"
}
collection() brukes inne i addDoc() for å angi hvilken database som skal brukes, og hvilken samling (collection) inne i databasen dataene skal skrives til. En samling i dokumentbaserte databaser tilsvarer som sagt omtrent en tabell i relasjonsdatabaser, og et dokument tilsvarer en rad. Koden for å lage en referanse til en elev blir derfor slik:
collection(_DATABASE_, "_NAVN_PÅ_COLLECTION_");
Husk å importere Firebase-funksjonene
Alle funksjonene du bruker som er spesielle for Firebase, og ikke generelle JavaScript-funksjoner, må importeres. Vi har allerede importert initializeApp fra (...)/firebase-app.js og getFirestore fra (...)/firebase-firestore.js i koden over. Når vi skal skrive kode videre, må vi huske å importere alle funksjoner vi ikke har brukt før fra (...)/firebase-firestore.js. For å bruke addDoc() og collection() må vi derfor legge dem inn i import-setningen over, rett etter import { getFirestore, slik:
import { getFirestore, addDoc, collection } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js"
Foran hvert kodeeksempel videre i teksten er det lagt inn en kommentar med hvilke funksjoner som må importeres for at koden skal fungere.
Legge inn en elev i databasen
Nå er du klar til å legge inn den første eleven i databasen. Skriv koden under nederst i scriptet ditt. Husk å skrive await foran funksjonen som starter kommunikasjon med databasen.
1// import { addDoc, collection } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js"; 2 3// Lager et nytt dokument i samlinga "elever" 4await addDoc( 5 collection(db, "elever"), { 6 fornavn: "Rebecca", 7 etternavn: "Thomasen", 8 telefon: "12345678" 9});
Lagre HTML-dokumentet og åpne det i en nettleser. Åpne inspiser-verktøyet for å sjekke at du ikke har noen feilmeldinger i konsollen, og se på Firestore-databasen din. Nå skal du finne et nytt dokument med dataene du la inn.

Opprette et nytt dokument i databasen med egendefinert ID
setDoc() er en annen måte å opprette nye dokumenter i databasen på. setDoc() gir deg muligheten til å definere en egen primærnøkkel for hvert dokument i databasen, slik at du kan bruke for eksempel brukernavn, e-post eller en egendefinert ID (elev-ID, kundenummer) som primærnøkkel. setDoc() brukes i kombinasjon med doc() for å angi hvor dokumentet skal lagres i databasen, og hva som skal være primærnøkkelen.
setDoc() er en funksjon for å skrive data til en spesifikk ID i databasen. Denne funksjonen tar inn to parametere: hvilket dokument dataene skal skrives til (angitt med ID), og hvilken data som skal skrives, slik:
setDoc(_DOCUMENT_, _DATA_);
Dataene skrives inn på formen
{
_FELTNAVN_1_: "_DATA_1_",
_FELTNAVN_2_: "_DATA_2_"
}
doc() brukes inne i setDoc(), for å angi hvilken database som skal brukes, hvilken samling (collection) inne i databasen dataene skal skrives til, og hvilken ID dokumentet skal ha. Koden for å lage en referanse til en elev blir derfor slik:
doc(_DATABASE_, "_NAVN_PÅ_COLLECTION_", "_ID_");
Merk at ID-en alltid må være definert som tekst, med anførselstegn. Hvis du ønsker å bruke nummer som ID, må du derfor også skrive tallet i anførselstegn, slik: "3".
Legge inn en elev i databasen
Nå er du klar til å legge inn en ny elev med egendefinert ID i databasen. Som ID velger vi å lage et brukernavn med de første bokstavene i etternavnet og de to første bokstavene i fornavnet. Importer funksjonene setDoc og doc fra (...)/firebase-firestore.js, og skriv koden under nederst i scriptet ditt. Husk å skrive await foran funksjonen som starter kommunikasjon med databasen.
1// import { setDoc, doc } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js"; 2 3// Lager et nytt dokument i samlinga "elever" 4await setDoc( 5 doc(db, "elever", "nilja"), { 6 fornavn: "Jakob", 7 etternavn: "Nilsen", 8 epost: "jakob@nilsen.net" 9 });
Lagre HTML-dokumentet og åpne det i en nettleser. Åpne inspiser-verktøyet for å sjekke at du ikke har noen feilmeldinger i konsollen, og se på Firestore-databasen din. Nå skal du finne et nytt dokument med dataene du la inn. Legg merke til at ID-en til dokumentet er det samme som vi anga i koden ("nilja").

Endre et dokument i databasen
Hvis du trenger å endre data i et dokument som allerede er lagret i databasen, kan du bruke funksjonen updateDoc(). Med updateDoc() kan du endre innholdet i felt i et dokument, eller du kan legge til nye felt. updateDoc() har samme syntaks (skrivemåte) som setDoc():
updateDoc(_DOCUMENT_, _DATA_);
Som med setDoc() bruker vi doc() for å hente ut dokumentet:
updateDoc(doc(_DATABASE_, "_COLLECTION_", "_ID_"), { _FELTNAVN_: "_DATA_" });
Vi kan for eksempel endre etternavn og legge til telefonnummer til eleven Jakob Nilsen, som vi nettopp la til. Importer først funksjonen updateDoc fra (...)/firebase-firestore.js, og skriv følgende kode nederst i scriptet ditt:
1// import { updateDoc, doc } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js"; 2 3// Endrer feltet "etternavn" i dokumentet og legger til feltet "telefon" 4await updateDoc( 5 doc(db, "elever", "nilja"), { 6 etternavn: "Nilssen", 7 telefon: "2233445" 8});

Vi har nå endret etternavnet fra Nilsen (én S) til Nilssen (to S-er) og lagt til et telefonnummer. Alle andre felt forblir uendret.
Slette et felt
Vi kan også bruke updateDoc() for å slette felt. Vi må da bruke funksjonen deleteField() inne i updateDoc(), slik:
feltnavn: deleteField()
Vi kan se i databasen at e-posten til Jakob Nilssen fortsatt er med en S, så den er sannsynligvis feil. For å slette e-posten skriver du koden under. Husk å importere deleteField().
1// import { updateDoc, doc, deleteField } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js"; 2 3// Sletter feltet "epost" fra dokumentet 4await updateDoc( 5 doc(db, "elever", "nilja"), { 6 epost: deleteField() 7});
Da vil hele e-postfeltet i dokumentet slettes.
Slette et dokument
For å slette et helt dokument kan du bruke funksjonen deleteDoc(). Denne funksjonen har ganske lik skrivemåte som setDoc() og updateDoc(), men her trenger du ikke å angi noen felt siden alle skal slettes. For å slette et dokument trenger du å vite ID-en til dokumentet. For å slette eleven Jakob Nilssen fra databasen skriver du koden under. Husk å importere deleteDoc()).
1// import { deleteDoc, doc } from "https://www.gstatic.com/firebasejs/9.6.3/firebase-firestore.js"; 2 3// Sletter dokumentet med ID-en "nilja" 4await deleteDoc( 5 doc(db, "elever", "nilja") 6);
Dokumentet er nå slettet fra databasen.
Relatert innhold
I denne guiden vil du lære et basisoppsett som du skal bruke videre i modulen "Lage en dynamisk webside med databasekobling i Firebase Cloud Firestore".
Når vi skal hente data fra Cloud Firestore, kan vi hente ut ett enkelt dokument, alle dokumentene i ei samling, eller vi kan hente data med spørringer.