Is there an 'OR' operator for a FireStore query in MongoDB?

Firestore: Sådan laver du logiske OR-forespørgsler

17/09/2024

Rating: 4.58 (5755 votes)

Mange udviklere, der kommer fra en baggrund med SQL-databaser eller endda MongoDB, støder ofte på en udfordring, når de begynder at arbejde med Cloud Firestore: Hvordan udfører man en logisk OR-forespørgsel? I modsætning til SQL's simple WHERE felt1 = 'A' OR felt2 = 'B', har Firestore historisk set haft en mere restriktiv tilgang til forespørgsler for at sikre skalerbarhed og ydeevne i verdensklasse. Dette har ført til kreative løsninger, men heldigvis har platformen udviklet sig.

How to create a logical OR query in Cloud Firestore?
How to create a logical OR query in Cloud Firestore with the JavaScript SDK? With Cloud Firestore, we can combine multiple where() methods to create logical AND queries. These queries are called compound queries in the documentation. However, as indicated in the documentation (Section “ Query Limitation s”):

I denne artikel vil vi dykke ned i de forskellige metoder til at opnå OR-funktionalitet i Firestore, fra de klassiske løsninger til den nye, indbyggede or()-operator, der har gjort livet meget lettere for udviklere. Vi vil se på, hvornår man skal bruge hvilken metode, og hvilke begrænsninger man stadig skal være opmærksom på.

Indholdsfortegnelse

Den Klassiske Udfordring: OR på Samme Felt

Det mest almindelige scenarie er, når du ønsker at finde dokumenter, hvor et enkelt felt kan have en af flere mulige værdier. Forestil dig, at du har en samling af brugere, og du vil hente alle, der har rollen 'Maker', 'Checker' eller 'Approver'.

En nybegynderfejl ville være at kæde where()-kald sammen som følger:

// DETTE VIRKER IKKE SOM ET OR! db.collection('users') .where('role', '==', 'Maker') .where('role', '==', 'Checker') .where('role', '==', 'Approver') .get();

Dette er en logisk AND-operation. Forespørgslen forsøger at finde brugere, hvis rolle er 'Maker' OG 'Checker' OG 'Approver' på samme tid, hvilket er umuligt. Løsningen her er at bruge in-operatoren.

How to create a logical OR query in Cloud Firestore?
How to create a logical OR query in Cloud Firestore with the JavaScript SDK? With Cloud Firestore, we can combine multiple where() methods to create logical AND queries. These queries are called compound queries in the documentation. However, as indicated in the documentation (Section “ Query Limitation s”):

Løsningen: `in`-operatoren

in-operatoren er designet præcist til dette formål. Den lader dig specificere en liste (array) af op til 30 værdier, og den vil returnere alle dokumenter, hvor det angivne felt matcher en af værdierne i listen.

Den korrekte forespørgsel ser således ud:

db.collection('users') .where('role', 'in', ['Maker', 'Checker', 'Approver']) .get();

Dette er den mest effektive og direkte måde at udføre en OR-operation på et enkelt felt. En lignende operator, array-contains-any, kan bruges, hvis dit felt er et array, og du vil finde dokumenter, hvor array-feltet indeholder mindst én af værdierne fra din liste.

Den Store Nyhed: Den Indbyggede `or()`-Operator

I lang tid var det største problem, når man havde brug for OR-logik på tværs af *forskellige* felter. For eksempel: "Find alle byer, der enten er en hovedstad ELLER ligger i Italien." Dette var tidligere ikke muligt med en enkelt forespørgsel.

Heldigvis har Firebase introduceret en native or()-operator, som løser netop dette problem. Den giver dig mulighed for at kombinere op til 30 separate betingelser i en enkelt, effektiv forespørgsel.

Does Order of where conditions matter when querying FireStore?
The order of where conditions does not matter when querying Firestore. Firebase has strict limitations on which queries are allowed, e.g. there cannot be two not-equals (!=) conditions in one query, read more below. Queries with where or order-by clauses on different fields need a composite index.

Sådan bruges `or()`

Ved at bruge den nye operator kan vi nu nemt løse vores eksempelproblem:

import { collection, query, where, or } from "firebase/firestore"; const citiesRef = collection(db, "cities"); const q = query(citiesRef, or(where("isCapital", "==", true), where("country", "==", "Italy")) ); // Nu kan du eksekvere forespørgslen 'q'

Denne kode udfører forespørgslen direkte på Firestores servere og returnerer et samlet resultat, der opfylder mindst én af betingelserne. Dette er en markant forbedring i forhold til de gamle metoder, der krævede, at man selv hentede og flettede data.

Den Gamle Metode: Fletning på Klientsiden (Legacy)

Før or()-operatoren eksisterede, var den eneste løsning på OR-problemet på tværs af forskellige felter at udføre flere separate forespørgsler og derefter manuelt flette resultaterne på klientsiden. Selvom denne metode nu er forældet i de fleste tilfælde, er det godt at kende den for at forstå udviklingen eller arbejde med ældre kodebaser.

Metoden fungerede typisk sådan her:

  1. Definer to (eller flere) separate forespørgsler.
  2. Udfør dem parallelt ved hjælp af Promise.all().
  3. Modtag resultaterne fra begge forespørgsler.
  4. Flet de to resultat-arrays sammen.
  5. Vigtigt: Fjern dubletter. Hvis en by f.eks. er både hovedstad og ligger i Italien (som Rom), vil den optræde i begge resultatsæt.
async function getCapitalsOrItalianCities() { const capitalsQuery = db.collection('cities').where('isCapital', '==', true).get(); const italianCitiesQuery = db.collection('cities').where('country', '==', 'Italy').get(); const [capitalsSnapshot, italianCitiesSnapshot] = await Promise.all([capitalsQuery, italianCitiesQuery]); const allCities = [ ...capitalsSnapshot.docs, ...italianCitiesSnapshot.docs ]; // Fjern dubletter ved hjælp af et Map baseret på dokumentets ID const uniqueCitiesMap = new Map(); allCities.forEach(doc => uniqueCitiesMap.set(doc.id, doc.data())); return Array.from(uniqueCitiesMap.values()); }

Denne metode virker, men den er mindre effektiv. Den kræver flere læsninger fra databasen, overfører potentielt mere data og lægger logikken for fletning og deduplikering over på klienten.

Oversigt over Løsninger

For at gøre det helt klart, hvornår du skal bruge hvilken metode, er her en sammenligningstabel.

Can I filter on multiple fields in Firestore?
Firestore now supports the in and array-contains-any operators, allowing you to query for up to 10 values in a single query to filter on multiple fields.
ScenarieAnbefalet LøsningVigtige Pointer
Flere mulige værdier i samme felt. (f.eks. status er 'ny' ELLER 'igangværende')Brug in operatoren:
where('status', 'in', ['ny', 'igangværende'])
Meget effektiv og hurtig. Den foretrukne metode til dette scenarie. Begrænset til 30 værdier.
Betingelser på forskellige felter. (f.eks. erHovedstad == true ELLER land == 'Italien')Brug den native or() operator:
or(where('isCapital', '==', true), where('country', '==', 'Italy'))
Moderne, effektiv og udføres på serveren. Den bedste løsning i dag. Kræver korrekt indeksering.
Komplekse forespørgsler, der ikke understøttes af or(), eller i ældre kodebaser.Udfør separate forespørgsler og flet resultaterne på klientsiden.Legacy-metode. Fleksibel, men mindre effektiv. Kræver manuel håndtering af dubletter.

Ofte Stillede Spørgsmål (FAQ)

Hvilken metode skal jeg vælge? Den gamle metode med at flette eller den nye `or()`-operator?

Du bør næsten altid vælge den nye, native or()-operator. Den er mere effektiv, da logikken håndteres af Firestore, hvilket reducerer mængden af data, der sendes til din klient, og forenkler din kode. Brug kun den manuelle fletningsmetode, hvis du støder på en af de få begrænsninger i or()-operatoren, eller hvis du arbejder i en ældre kodebase, der ikke kan opdateres.

Har rækkefølgen af `where`-betingelser betydning?

Nej, rækkefølgen af dine where-betingelser i en standardforespørgsel eller inde i en or()-funktion har ingen betydning for resultatet. Firestore-optimeringsmotoren håndterer dem. Rækkefølgen har dog stor betydning for orderBy()-klausuler, hvor den første klausul har højeste prioritet.

Hvad med indeksering?

Ligesom med andre komplekse forespørgsler i Firestore, kræver or()-forespørgsler ofte sammensatte indekser. Hvis din forespørgsel fejler, vil Firestore typisk give en fejlmeddelelse med et direkte link til at oprette det nødvendige indeks i Firebase-konsollen. Det er afgørende at oprette disse indekser for at sikre, at dine forespørgsler forbliver hurtige, uanset hvor meget data du har.

Hvis du vil læse andre artikler, der ligner Firestore: Sådan laver du logiske OR-forespørgsler, kan du besøge kategorien Teknologi.

Go up