MongoDB Academy · Lektion

Fråga efter arrayer: $all, $size och elementmatchning

Ni filtrerar dokument efter arrayinnehåll med $all för matchning av flera element och $size för kontroller av längden.

Lektion 1 av 413 steg

Fråga efter arrayer: $all, $size och elementmatchning är en gratis lektion i MongoDB Academy på CoddyKit. Detta är lektion 1 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.

Arrayer som förstaklassmedborgare

I MongoDB är arrayer en inbyggd BSON-typ som kan lagras direkt i ett dokumentfält. Till skillnad från relationsdatabaser, där arrayer kräver en separat kopplingstabell, låter MongoDB er bädda in arrayer av valfri typ – skalärer, underdokument eller blandade typer – direkt i dokumentet. Det gör arrayer till en av de mest användbara funktionerna, men också till en av de mest nyanserade att fråga på rätt sätt.

// Documents with array fields
db.products.insertMany([
  { name: 'Laptop', tags: ['electronics', 'computers', 'portable'] },
  { name: 'Mouse', tags: ['electronics', 'peripherals'] },
  { name: 'Book', tags: ['education', 'reading'] }
]);

Enkla frågor med arraylikhet

Ett enkelt likhetsfilter på ett arrayfält kontrollerar om arrayen innehåller det angivna värdet som ett element. Ni behöver ingen särskild operator – skriv bara filtret som om fältet vore en skalär. MongoDB matchar alla dokument där arrayen innehåller exakt det värdet, oavsett var i arrayen det förekommer.

// Find products tagged 'electronics'
// MongoDB checks if 'electronics' is an element of the tags array
db.products.find({ tags: 'electronics' });
// Returns Laptop and Mouse (both have 'electronics' in tags)

// This also works on arrays of numbers
db.scores.find({ values: 95 });
// Matches { values: [80, 95, 72] }

Operatorn $all

$all-operatorn matchar dokument där arrayen innehåller alla angivna värden, i valfri ordning. Till skillnad från en vanlig likhetskontroll (som matchar ett enda element) kräver $all att varje angivet element finns med. Se det som flera AND-villkor för medlemskap i arrayen.

// Find products tagged BOTH 'electronics' AND 'portable'
db.products.find({
  tags: { $all: ['electronics', 'portable'] }
});
// Returns Laptop (has both tags)
// Does NOT return Mouse (missing 'portable')

// Order of values in $all does not matter
db.products.find({
  tags: { $all: ['portable', 'electronics'] }  // same result
});

Operatorn $size

$size-operatorn matchar dokument där arrayfältet innehåller exakt det angivna antalet element. Den accepterar ett bokstavligt heltal – Ni kan inte använda intervalljämförelser som $gt direkt med $size. För längdkontroller baserade på intervall kan Ni använda ett fält som lagrar arrayens längd bredvid arrayen, eller använda en aggregation med $where.

// Find products with exactly 3 tags
db.products.find({ tags: { $size: 3 } });
// Returns Laptop (tags has 3 elements)

// $size does NOT support ranges:
// db.products.find({ tags: { $size: { $gt: 2 } } }); // INVALID

// Workaround: store the count as a field
db.products.updateMany({}, [{ $set: { tagCount: { $size: '$tags' } } }]);
db.products.find({ tagCount: { $gt: 2 } });  // range check on stored count

Matchning efter arrayindex

Ni kan söka efter en specifik position i en array med punktnotation och ett indexnummer. Exempelvis matchar { 'scores.0': 100 } dokument där det första elementet i arrayen scores är 100. Detta är användbart när arrayens ordning har betydelse, till exempel i en rangordnad lista eller en tidsordnad sekvens.

// Documents: { name: 'Alice', scores: [100, 85, 92] }
//            { name: 'Bob',   scores: [75, 88, 91] }

// Find documents where the FIRST score is 100
db.results.find({ 'scores.0': 100 });
// Returns Alice

// Find where SECOND element is greater than 85
db.results.find({ 'scores.1': { $gt: 85 } });
// Returns Bob (scores[1] = 88 > 85) and Alice (85 is NOT > 85)

Problemet med spridda fält

En subtil fallgrop är att MongoDB tillämpar varje villkor oberoende över alla arrayelement – inte på ett enda element – när Ni filtrerar en array med underdokument med flera villkor på olika fält. Detta kallas problemet med spridda fält. Exempelvis matchar { 'scores.value': { $gt: 90 }, 'scores.grade': 'A' } om något element har värdet > 90 OCH något element har betyget 'A' – de behöver inte vara samma element.

// Documents:
// { scores: [{ value: 95, grade: 'A' }, { value: 60, grade: 'D' }] }
// { scores: [{ value: 92, grade: 'B' }, { value: 72, grade: 'C' }] }

// This filter has SPREAD FIELD issue:
// Matches doc1 (value 95>90 is in scores[0], grade 'A' is in scores[0] - fine here)
// Also matches doc2 if value 92>90 from one element + some 'B'... but what if:
// { scores: [{ value: 91, grade: 'B' }, { value: 62, grade: 'A' }] }
// This would ALSO match! 91 > 90 from element[0] + grade 'A' from element[1]

$elemMatch för arrayfrågor med flera villkor

$elemMatch-frågeoperatorn löser problemet med spridda fält genom att kräva att alla villkor uppfylls av samma enskilda arrayelement. Omslut villkoren med { $elemMatch: { condition1, condition2 } }, så returnerar MongoDB endast dokument där minst ett arrayelement uppfyller alla angivna villkor samtidigt.

// Find documents where a SINGLE scores element has value > 90 AND grade 'A'
db.results.find({
  scores: {
    $elemMatch: {
      value: { $gt: 90 },
      grade: 'A'
    }
  }
});
// Only matches if one element has BOTH value > 90 AND grade 'A'

$elemMatch för skalära arrayer

$elemMatch kan även användas på arrayer med skalära värden (strängar och tal) när Ni behöver tillämpa flera operatorer på samma element. Exempelvis för att hitta element som både är större än 10 och mindre än 20 – utan $elemMatch skulle dessa villkor kunna uppfyllas av två olika element.

// Find docs where a SINGLE element is between 10 and 20
db.measurements.find({
  values: { $elemMatch: { $gt: 10, $lt: 20 } }
});
// { values: [5, 15, 25] } - matches (15 satisfies both)
// { values: [5, 30] }     - does NOT match

// Without $elemMatch (wrong - tests across elements):
db.measurements.find({ values: { $gt: 10, $lt: 20 } });
// { values: [5, 30] } WOULD match! (5 < 20, 30 > 10, different elements)

Kombinera $all och $elemMatch

Ni kan använda $all med $elemMatch-uttryck inuti för att kräva flera komplexa villkor över flera olika arrayelement. Varje $elemMatch inuti $all måste uppfyllas av ett annat element. Detta mönster behövs sällan, men är tillgängligt för komplexa krav med flera villkor och flera element.

// Find docs where:
// - one element satisfies { value: { $gt: 90 }, grade: 'A' }
// - AND another element satisfies { value: { $lt: 70 }, grade: 'D' }
db.results.find({
  scores: {
    $all: [
      { $elemMatch: { value: { $gt: 90 }, grade: 'A' } },
      { $elemMatch: { value: { $lt: 70 }, grade: 'D' } }
    ]
  }
});

Arrayer och indexbeteende

Ett index på ett arrayfält blir automatiskt ett multikey-index i MongoDB, med en indexpost per arrayelement. Det innebär att frågor som { tags: 'electronics' } och { tags: { $all: ['electronics', 'portable'] } } båda drar nytta av indexet. Ett sammansatt index kan dock inte ha multikey för mer än ett arrayfält per dokument – ett försök att göra det genererar ett fel.

// Index on tags field becomes multikey automatically
db.products.createIndex({ tags: 1 });

// These queries all use the multikey index efficiently:
db.products.find({ tags: 'electronics' });
db.products.find({ tags: { $all: ['electronics', 'portable'] } });
db.products.find({ tags: { $size: 3 } });
// Note: $size cannot use the index for size filtering
// (it still needs to check document-level array length)

Använda explain() med arrayfrågor

Arrayfrågor med $all och $elemMatch kan ibland ge oväntad indexanvändning. Kontrollera alltid med explain('executionStats'). Ett $size-filter visar IXSCAN på multikey-indexet men granskar ändå alla indexposter, eftersom storleken inte lagras i indexet. En $elemMatch på indexerade fält använder IXSCAN för de matchande elementvillkoren.

// Check how array queries use indexes
db.products.find({
  tags: { $all: ['electronics', 'portable'] }
}).explain('executionStats');

// Look for:
// stage: 'IXSCAN' - index is being used
// totalKeysExamined vs nReturned ratio

Snabb kontroll

Testa Er förståelse av operatorer för arrayfrågor i MongoDB.

Sammanfattning av lektionen

I den här lektionen har Ni lärt Er att $all kräver att en array innehåller alla angivna värden, att $size matchar arrayer med ett exakt antal element och att $elemMatch säkerställer att flera villkor gäller för samma enskilda arrayelement, vilket löser problemet med spridda fält. Nästa steg är att gå djupare in på $elemMatch för matchning av arrayens underdokument.

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 ”Fråga efter arrayer: $all, $size och elementmatchning” gratis?

Ja – hela texten till ”Fråga efter arrayer: $all, $size och elementmatchning” 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 ”Fråga efter arrayer: $all, $size och elementmatchning”?

Ni filtrerar dokument efter arrayinnehåll med $all för matchning av flera element och $size för kontroller av längden. 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 1 av 4.

Hur lång tid tar lektionen ”Fråga efter arrayer: $all, $size och elementmatchning”?

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. Fråga efter arrayer: $all, $size och elementmatchning
  2. $elemMatch: matcha underdokument i arrayer
  3. Uppdatera arrayer: $push, $pull, $pop och $addToSet
  4. Positionella och filtrerade positionella uppdateringar
← Tillbaka till MongoDB Academy