MongoDB Academy · Lektion

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

Kombinera flera villkor med logiska operatorer för att uttrycka sammansatt filterlogik.

Lektion 2 av 413 steg

Logiska operatorer: $and, $or, $nor, $not är en gratis lektion i MongoDB Academy på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för MongoDB Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i MongoDB Academy innehåller totalt 4 lektioner.

Varför logiska operatorer behövs

De flesta frågefilter innehåller villkor för flera fält, och alla bör inte kombineras med ett enkelt AND. Ibland vill ni ha dokument som uppfyller något av flera villkor, eller så vill ni utesluta dokument som matchar ett mönster. MongoDB:s logiska operatorer – $and, $or, $nor och $not – ger er full boolesk kontroll över filtervillkoren.

Genom att förstå när varje operator ska användas – och känna till genvägen med implicit AND – blir era frågor mer lättlästa och effektiva.

Implicit AND: Standard

När du listar flera fältvillkor i ett och samma filterobjekt tillämpar MongoDB dem som ett implicit AND—alla villkor måste vara sanna för att ett dokument ska matcha. Detta är standardfallet och det vanligaste scenariot.

Implicit AND är både mer koncist och något effektivare än den explicita operatorn $and, eftersom MongoDB kan optimera villkor på fältnivå var för sig. Använd implicit AND när villkoren gäller olika fält och det inte finns någon tvetydighet.

// 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' }
  ]
});

När explicit $and behövs

Explicit $and krävs i en specifik situation: när du behöver tillämpa flera villkor på samma fält med olika operatorer och inte kan uttrycka dem i ett enda objekt (eftersom JavaScript-objekt inte kan ha dubbla nycklar).

Det vanligaste fallet är att kombinera två $or-villkor som båda refererar till fältet. Intervallvillkor på ett och samma fält ({ price: { $gte: 20, $lte: 100 } }) fungerar däremot bra i ett enda objekt—explicit $and behövs bara när uttrycken inte kan kombineras till ett enda fältvärde.

// 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: Minst ett villkor

$or tar en array med filtervillkor och matchar dokument där minst ett av villkoren är sant. Det motsvarar SQL:s nyckelord OR i MongoDB.

Använd $or när du har alternativa vägar till samma resultat—till exempel när du vill hitta användare som antingen är administratörer eller har varit aktiva under de senaste 30 dagarna. En viktig prestandaaspekt är att MongoDB kan använda indexunion för att uppfylla frågan om varje villkor är indexerat separat—men ett enda sammansatt index som täcker alla villkor är ofta snabbare.

// 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: Inget av villkoren

$nor matchar dokument där inget av de angivna villkoren är sant—det är komplementet till $or. Ett dokument måste inte uppfylla ALLA villkor i $nor-arrayen för att returneras.

$nor är mindre vanligt än $or, men är användbart för exkluderingslogik: ”hitta produkter som varken har utgått, är slut i lager eller tillhör den arkiverade kategorin”. Det matchar även dokument där de efterfrågade fälten saknas, eftersom saknade fält inte matchar något positivt villkor.

// 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: Negera en enskild operator

$not inverterar resultatet av ett uttryck med en operator på fältnivå. Till skillnad från $nor (som tar en array med fullständiga filtervillkor) omsluter $not en enskild operator eller ett reguljärt uttryck: { price: { $not: { $gt: 100 } } }.

$not matchar även dokument där fältet inte finns. Den är ofta överflödig tillsammans med $ne eller $nin, men är särskilt användbar för att negera reguljära uttryck: { name: { $not: /^admin/i } }—det finns ingen motsvarighet till $ne för reguljära uttryck.

// $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'] } }
});

Kombinera $and, $or och $not

Logiska operatorer kan nästlas för att uttrycka godtyckligt komplex boolesk logik. Tänk på det som att bygga ett logiskt träd: yttre $and-villkor kopplas samman på den översta nivån, medan $or-underuttryck uttrycker alternativ inom en gren.

Komplexa nästlade booleska frågor kan vara svåra att läsa—överväg att dela upp dem i namngivna JavaScript-variabler eller bygga filterobjektet programmatiskt utifrån användarinmatning, i stället för att nästla dem fem nivåer djupt i en enda objektliteral.

// 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);

Prestandaaspekter för $or

$or-frågor har ett särskilt beteende när det gäller indexanvändning. MongoDB utvärderar varje gren i $or separat och slår samman resultaten:

  • Om varje gren kan använda ett index utför MongoDB en indexunion—effektivt
  • Om någon gren inte kan använda ett index återgår MongoDB till en samlingsgenomsökning för den grenen—vilket kan vara långsamt

För bästa prestanda bör du se till att varje gren i $or har ett motsvarande index. När $or-villkor kan skrivas om som $in på samma fält ({ status: { $in: ['a','b'] } }) bör du göra det—$in är effektivare än en $or med två grenar på samma fält.

// 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

Logiska operatorer i aggregeringspipen

I aggregeringspipeline-steg som $match fungerar samma logiska operatorer exakt som i find(). Placera $match med dina logiska villkor så tidigt som möjligt i pipen för att minska antalet dokument som efterföljande steg behöver bearbeta.

I pipelineuttryckens operatorer (som $project eller $addFields) har logiska operatorer en något annorlunda syntax: { $and: [expr1, expr2] } som uttrycksoperatorer i stället för frågeoperatorer. Frågekontexter ($match) och uttryckskontexter ($project) använder samma operatörsnamn men olika syntax.

// $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 } } }
]);

Praktiskt mönster för filterbyggare

I riktiga applikationer byggs frågefilter ofta dynamiskt utifrån användarinmatning (sökformulär och API-frågeparametrar). Bygg filterobjektet programmatiskt och lägg bara till villkor när parametern har angetts—lägg inte till en $or: [] med tomma arrayer, eftersom det inte skulle matcha något.

Validera och sanera alla värden från användaren innan du tar med dem i en fråga. Skicka aldrig råa användarsträngar direkt till $regex utan att escapa dem—en angripare kan injicera ett katastrofalt långsamt reguljärt uttryck (en ReDoS-attack).

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();

Kortslutningsutvärdering i MongoDB

MongoDB utvärderar uttryck med logiska operatorer, men tillämpar INTE nödvändigtvis kortslutning på samma sätt som JavaScript. Frågeplaneraren kan ändra ordningen på villkoren för att effektivisera frågan—till exempel flytta ett villkor som använder ett index före ett som inte gör det, oavsett deras ordning i frågedokumentet.

En viktig följd är att i , om den första grenen orsakar en fullständig samlingsgenomsökning, kan hela frågan genomsöka samlingen även om den andra grenen använder ett effektivt index. Därför är det så viktigt för prestandan att se till att varje gren i är indexerad. Använd explain() för att kontrollera att körningsplanen motsvarar dina förväntningar.

// 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')

Snabbkontroll

Testa dina kunskaper om MongoDB och NoSQL-databaser från den här lektionen.

Sammanfattning av lektionen

I den här lektionen har du lärt dig att implicit AND är standard när du listar flera fält i ett filterobjekt—explicit $and behövs bara när du inte kan uttrycka villkoren som unika nycklar (till exempel två $or-block), att $or matchar vilket som helst av villkoren och använder indexunion när varje gren är indexerad, samt att $not inverterar en enskild operator och är särskilt användbar för att negera reguljära uttryck där $ne inte kan användas. Nästa steg är elementoperatorer som $exists och $type för hantering av valfria fält och fält med blandade typer.

Gratis att börja

Lär dig JavaScript med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Logiska operatorer: $and, $or, $nor, $not” gratis?

Ja – hela texten till ”Logiska operatorer: $and, $or, $nor, $not” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i MongoDB Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i MongoDB Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Logiska operatorer: $and, $or, $nor, $not”?

Kombinera flera villkor med logiska operatorer för att uttrycka sammansatt filterlogik. Ni övar på MongoDB Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig MongoDB Academy?

Du behöver inga förkunskaper. Utbildningen i MongoDB Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.

Hur lång tid tar lektionen ”Logiska operatorer: $and, $or, $nor, $not”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här MongoDB Academy-lektionen?

Ja. Varje MongoDB Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Jämförelseoperatorer: $eq, $gt, $lt, $in
  2. Logiska operatorer: $and, $or, $nor, $not
  3. Elementoperatorer och typkontroller
  4. Regex-frågor och mönstermatchning
← Tillbaka till MongoDB Academy