MongoDB Academy · Lektion

Logiske operatorer: $and, $or, $nor, $not

Kombiner flere betingelser med logiske operatorer for at udtrykke sammensat filterlogik.

Lektion 2 af 413 trin

Logiske operatorer: $and, $or, $nor, $not er en gratis MongoDB Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i MongoDB Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. MongoDB Academy-kurset indeholder 4 lektioner i alt.

Hvorfor logiske operatorer er nødvendige

De fleste forespørgselsfiltre indeholder betingelser for flere felter, og de skal ikke alle kombineres med et simpelt AND. Nogle gange ønsker du dokumenter, der opfylder en hvilken som helst af flere betingelser, eller du vil udelukke dokumenter, der matcher et mønster. MongoDB's logiske operatorer – $and, $or, $nor og $not – giver dig fuld boolesk kontrol over filterbetingelserne.

Når du forstår, hvornår hver operator skal bruges, og kender genvejen med implicit AND, bliver dine forespørgsler mere læsbare og effektive.

Implicit AND: Standardindstillingen

Når du angiver flere feltbetingelser i ét filterobjekt, anvender MongoDB et implicit OG—alle betingelser skal være sande, for at et dokument matcher. Dette er standardtilfældet og det mest almindelige.

Det implicitte OG er både mere kompakt og en smule mere effektivt end den eksplicitte operator $and, fordi MongoDB kan optimere betingelser på feltniveau uafhængigt af hinanden. Brug implicit OG, når dine betingelser målretter forskellige felter uden tvetydighed.

// Implicit AND - all three conditions must be true
db.users.find({
  age: { $gte: 18 },
  active: true,
  role: 'user'
});
// Equivalent to: age >= 18 AND active = true AND role = 'user'

// Same with explicit $and (more verbose, same result)
db.users.find({
  $and: [
    { age: { $gte: 18 } },
    { active: true },
    { role: 'user' }
  ]
});

Hvornår du har brug for eksplicit $and

Eksplicit $and er nødvendigt i én bestemt situation: når du skal anvende flere betingelser på det samme felt med forskellige operatorer, og du ikke kan udtrykke dem i ét objekt (fordi JavaScript-objekter ikke kan have dublerede nøgler).

Det mest almindelige tilfælde er at kombinere to $or-betingelser, der begge refererer til feltet. Intervalbetingelser på ét felt ({ price: { $gte: 20, $lte: 100 } }) fungerer dog fint i ét objekt—eksplicit $and er kun nødvendigt, når udtrykkene ikke kan kombineres til én feltværdi.

// Explicit $and: two $or conditions that cannot be merged
db.products.find({
  $and: [
    { $or: [{ category: 'Electronics' }, { category: 'Computers' }] },
    { $or: [{ brand: 'Apple' }, { brand: 'Samsung' }] }
  ]
});
// (category is Electronics OR Computers)
// AND (brand is Apple OR Samsung)

// If you just wrote { $or: [...], $or: [...] }
// JS would only keep the last $or!

$or: Mindst én betingelse

$or tager et array med filterbetingelser og matcher dokumenter, hvor mindst én af betingelserne er sand. Det svarer i MongoDB til SQL-nøgleordet OR.

Brug $or, når du har alternative veje til det samme resultat—for eksempel når du vil finde brugere, der enten er administratorer eller har været aktive inden for de seneste 30 dage. En vigtig bemærkning om ydeevne: Hvis hver betingelse har sit eget indeks, kan MongoDB bruge indeksforening til at opfylde forespørgslen—men ét sammensat indeks, der dækker alle betingelser, er ofte hurtigere.

// Find users who are admins OR have been recently active
const recentDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
db.users.find({
  $or: [
    { role: 'admin' },
    { lastLoginAt: { $gte: recentDate } }
  ]
});

// Find products on sale OR low in stock
db.products.find({
  $or: [
    { onSale: true },
    { stock: { $lt: 5 } }
  ]
});

$nor: Ingen af betingelserne

$nor matcher dokumenter, hvor ingen af de angivne betingelser er sande—det er komplementet til $or. Et dokument skal fejle ved ALLE betingelser i $nor-arrayet for at blive returneret.

$nor er mindre almindelig end $or, men er nyttig til udelukkelseslogik: »find produkter, der hverken er udgået, er udsolgt eller tilhører den arkiverede kategori«. Den matcher også dokumenter, hvor de forespurgte felter mangler, eftersom manglende felter ikke matcher nogen positiv betingelse.

// Exclude multiple status values
db.orders.find({
  $nor: [
    { status: 'cancelled' },
    { status: 'refunded' },
    { status: 'archived' }
  ]
});
// Matches orders where status is NONE of the above
// (equivalent to status NOT IN [...])

// Could also write as:
db.orders.find({ status: { $nin: ['cancelled', 'refunded', 'archived'] } });

$not: Negér én operator

$not vender resultatet af ét operatorudtryk på feltniveau om. I modsætning til $nor (som tager et array med komplette filterbetingelser) omslutter $not én operator eller ét regulært udtryk: { price: { $not: { $gt: 100 } } }.

$not matcher også dokumenter, hvor feltet ikke findes. Den er ofte overflødig sammen med $ne eller $nin, men er specifikt nyttig til at negere regulære udtryk: { name: { $not: /^admin/i } }—der findes ingen tilsvarende $ne for regulære udtryk.

// $not with a comparison operator
db.products.find({
  price: { $not: { $gt: 100 } }
});
// Matches: price <= 100 AND documents where price field is absent

// $not with a regex - negate a pattern
db.users.find({
  username: { $not: /^admin/i }
});
// Users whose username does NOT start with 'admin' (case-insensitive)

// Negating $in
db.items.find({
  status: { $not: { $in: ['draft', 'archived'] } }
});

Kombination af $and, $or og $not

Logiske operatorer kan indlejres for at udtrykke vilkårligt kompleks boolesk logik. Tænk på det som at bygge et logiktræ: Ydre $and-betingelser forbindes på øverste niveau, mens $or-underudtryk udtrykker alternativer i en gren.

Komplekse indlejrede booleske forespørgsler kan være svære at læse—overvej at opdele dem i navngivne JavaScript-variabler eller bygge filterobjektet programmatisk ud fra brugerinput i stedet for at indlejre dem fem niveauer dybt i ét objektliterale.

// Complex: (premium OR admin) AND (active) AND NOT (suspended)
db.users.find({
  $and: [
    { $or: [{ role: 'premium' }, { role: 'admin' }] },
    { active: true },
    { suspended: { $not: { $eq: true } } }
  ]
});

// Programmatic filter building (cleaner)
const filter = {};
if (roles.length > 0) filter['$or'] = roles.map(r => ({ role: r }));
if (activeOnly) filter.active = true;
db.users.find(filter);

Overvejelser om $or-ydeevne

$or-forespørgsler har en særlig adfærd for indeksbrug. MongoDB evaluerer hver gren af $or uafhængigt og fletter resultaterne:

  • Hvis hver gren kan bruge et indeks, udfører MongoDB en indeksforening—effektivt
  • Hvis en vilkårlig gren ikke kan bruge et indeks, falder MongoDB tilbage til en scanning af samlingen for den gren—det kan være langsomt

Sørg for, at hver gren af $or har et tilsvarende indeks, for at opnå den bedste ydeevne. Når $or-betingelser kan omskrives til $in på det samme felt ({ status: { $in: ['a','b'] } }), bør du gøre det—$in er mere effektiv end en $or med to grene på det samme felt.

// Inefficient: $or that prevents index use
db.products.find({
  $or: [
    { price: { $lt: 50 } },
    { description: { $regex: 'sale' } }  // Regex on unindexed field = COLLSCAN
  ]
});
// The regex branch causes a full scan for all matched documents

// Better: use $in when possible (same field, multiple values)
db.products.find({ category: { $in: ['A', 'B', 'C'] } });
// Single index lookup is more efficient than 3-branch $or

Logiske operatorer i aggregerings-pipelinen

I trin i aggregerings-pipelinen som $match fungerer de samme logiske operatorer præcis som i find(). Placér $match med dine logiske betingelser så tidligt som muligt i pipelinen for at reducere antallet af dokumenter, der behandles af efterfølgende trin.

Inde i pipelineudtryk med operatorer (som $project eller $addFields) har logiske operatorer en lidt anderledes syntaks: { $and: [expr1, expr2] } som udtryksoperatorer i stedet for forespørgselsoperatorer. Forespørgsels- ($match-) og udtrykskontekster ($project) bruger de samme operatornavne, men forskellige syntakser.

// $match with logical operators in an aggregation pipeline
db.orders.aggregate([
  {
    $match: {
      $or: [
        { status: 'shipped' },
        { status: 'delivered' }
      ],
      createdAt: { $gte: new Date('2024-01-01') }
    }
  },
  { $group: { _id: '$customerId', totalOrders: { $sum: 1 } } }
]);

Praktisk mønster til filterbygning

I virkelige applikationer bygges forespørgselsfiltre ofte dynamisk ud fra brugerinput (søgeformularer, API-parametre). Byg filterobjektet programmatisk, og tilføj kun betingelser, når parameteren er angivet—tilføj ikke et $or: [] med tomme arrays, da det ikke matcher noget.

Validér og rens alle brugerværdier, før du inkluderer dem i en forespørgsel. Send aldrig rå brugerstrenge direkte til $regex uden at escape dem—en angriber kan indsætte et katastrofalt langsomt regulært udtryk (et ReDoS-angreb).

function buildProductFilter(params) {
  const filter = {};

  if (params.categories && params.categories.length > 0) {
    filter.category = { $in: params.categories };
  }
  if (params.minPrice != null) {
    filter.price = { ...filter.price, $gte: params.minPrice };
  }
  if (params.maxPrice != null) {
    filter.price = { ...filter.price, $lte: params.maxPrice };
  }
  if (params.inStockOnly) {
    filter.stock = { $gt: 0 };
  }

  return filter;
}

const results = await db.collection('products')
  .find(buildProductFilter(req.query)).toArray();

Kortslutningsevaluering i MongoDB

MongoDB evaluerer udtryk med logiske operatorer, men laver IKKE nødvendigvis kortslutning som JavaScript. Forespørgselsplanlæggeren kan omarrangere betingelser af hensyn til effektiviteten—for eksempel flytte en betingelse, der bruger et indeks, foran en, der ikke gør, uanset deres rækkefølge i forespørgselsdokumentet.

En vigtig konsekvens er, at hvis den første gren medfører en fuld scanning af samlingen, kan hele forespørgslen scanne samlingen, selv om den anden gren har et effektivt indeks. Derfor er det så vigtigt for ydeevnen at sikre, at hver gren af er indekseret. Brug explain() til at kontrollere, at udførelsesplanen svarer til dine forventninger.

// MongoDB may reorder these conditions for efficiency:
db.products.find({
  : [
    { category: 'Electronics' },     // If indexed: fast point lookup
    { description: /wireless/i }     // Not indexed: slow scan
  ]
});
// Even though category (indexed) is listed first,
// if MongoDB cannot use index union, it may scan all docs.
// Always verify with .explain('executionStats')

Hurtigt tjek

Test din forståelse af begreberne MongoDB og NoSQL-databaser fra denne lektion.

Opsummering af lektionen

I denne lektion har du lært: implicit OG er standarden, når du angiver flere felter i ét filterobjekt—eksplicit $and er kun nødvendigt, når du ikke kan udtrykke betingelser som entydige nøgler (f.eks. to $or-blokke), $or matcher enhver enkelt betingelse og bruger indeksforening, når hver gren er indekseret, og $not vender én operator om og er især nyttig til at negere regulære udtryk, hvor $ne ikke kan bruges. Nu ser vi nærmere på elementoperatorer som $exists og $type til håndtering af valgfrie felter og felter med blandede typer.

Gratis at komme i gang

Lær JavaScript med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
30
Lektioner
120

Ofte stillede spørgsmål

Er lektionen “Logiske operatorer: $and, $or, $nor, $not” gratis?

Ja — hele teksten til “Logiske operatorer: $and, $or, $nor, $not” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af MongoDB Academy-kurset, skal du opgradere til CoddyKit PRO. MongoDB Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Logiske operatorer: $and, $or, $nor, $not”?

Kombiner flere betingelser med logiske operatorer for at udtrykke sammensat filterlogik. Du øver dig i MongoDB Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på MongoDB Academy?

Der kræves ingen tidligere erfaring. MongoDB Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Logiske operatorer: $and, $or, $nor, $not”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne MongoDB Academy-lektion?

Ja. Alle MongoDB Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Sammenligningsoperatorer: $eq, $gt, $lt, $in
  2. Logiske operatorer: $and, $or, $nor, $not
  3. Elementoperatorer og typekontrol
  4. Regex-forespørgsler og mønstermatch
← Tilbage til MongoDB Academy