$elemMatch: subdocumenten in arrays matchen
U gebruikt $elemMatch om meerdere voorwaarden op één array-element toe te passen en valse positieven door matching van verspreide velden te voorkomen.
$elemMatch: subdocumenten in arrays matchen is een gratis MongoDB Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject MongoDB Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus MongoDB Academy bevat in totaal 4 lessen.
Het patroon van arrays met subdocumenten
In MongoDB is het gebruikelijk om arrays met ingebedde subdocumenten—objecten met meerdere velden—op te slaan in een bovenliggend document. Voorbeelden zijn bestellingen met bestelregels, gebruikers met meerdere adressen of studenten met scores per vak. Voor query's op deze structuren is zorgvuldigheid nodig om het probleem van verspreide velden te voorkomen, waarbij voorwaarden op verschillende array-elementen worden gematcht.
// Example: student with per-subject scores
db.students.insertMany([
{
name: 'Alice',
scores: [
{ subject: 'math', score: 95, grade: 'A' },
{ subject: 'english', score: 72, grade: 'C' }
]
},
{
name: 'Bob',
scores: [
{ subject: 'math', score: 68, grade: 'D' },
{ subject: 'english', score: 91, grade: 'A' }
]
}
]);Het probleem van verspreide velden opnieuw bekeken
Wanneer je een array met subdocumenten filtert door rechtstreeks velden in puntnotatie te gebruiken, past MongoDB elke voorwaarde onafhankelijk toe op een willekeurig element in de array. De query { 'scores.subject': 'math', 'scores.grade': 'A' } matcht een document als een element subject='math' heeft EN een (mogelijk ander) element grade='A' heeft. Dit gedrag met fout-positieven is het probleem van verspreide velden.
// Problematic query - spread field issue
db.students.find({
'scores.subject': 'math',
'scores.grade': 'A'
});
// Returns BOTH Alice AND Bob!
// Alice: scores[0] has subject='math', scores[0] has grade='A' -> correct match
// Bob: scores[0] has subject='math' + scores[1] has grade='A' -> false positive!$elemMatch lost het probleem van verspreide velden op
$elemMatch is de oplossing: de operator beperkt alle voorwaarden tot hetzelfde afzonderlijke array-element. MongoDB retourneert een document alleen als ten minste één element in de array tegelijkertijd aan elke voorwaarde in het $elemMatch-blok voldoet. Dit is de juiste manier om query's uit te voeren op arrays met subdocumenten en meerdere voorwaarden.
// Correct query with $elemMatch
db.students.find({
scores: {
$elemMatch: {
subject: 'math',
grade: 'A'
}
}
});
// Returns ONLY Alice (scores[0] has BOTH subject='math' AND grade='A')
// Bob is excluded: no single element satisfies both conditionsBereikoperators gebruiken binnen $elemMatch
Je kunt elke MongoDB-queryoperator binnen $elemMatch gebruiken, waaronder bereikoperators zoals $gt, $lte en $in. Hiermee kun je voorwaarden uitdrukken zoals 'zoek een element waarvan de score tussen 80 en 100 ligt EN waarvan het vak wiskunde is'—voorwaarden die voor één specifiek element waar moeten zijn.
// Find students with a math score above 80
db.students.find({
scores: {
$elemMatch: {
subject: 'math',
score: { $gt: 80 }
}
}
});
// Returns Alice (math score is 95 > 80)
// With $in inside $elemMatch
db.students.find({
scores: {
$elemMatch: {
subject: { $in: ['math', 'science'] },
grade: 'A'
}
}
});Resultaten van $elemMatch ontkennen
Je kunt een $elemMatch-voorwaarde ontkennen met $not om documenten te vinden waarin geen array-element aan alle voorwaarden voldoet. Zo betekent 'vind studenten die GEEN A voor wiskunde hebben' dat 'geen enkel element zowel subject=math als grade=A heeft'. Dit is nauwkeuriger dan controleren op { 'scores.grade': { $ne: 'A' } }, want daarmee sluit je studenten uit die voor welk vak dan ook een A hebben.
// Students who do NOT have a math A
db.students.find({
scores: {
$not: {
$elemMatch: {
subject: 'math',
grade: 'A'
}
}
}
});
// Returns Bob (his math score is D, not A)$elemMatch in projectie
$elemMatch kan ook in de projectie (het tweede argument van find()) worden gebruikt om alleen het eerste array-element te retourneren dat aan een voorwaarde voldoet. Bij gebruik in een projectie heet dit de $elemMatch-projectieoperator (dezelfde naam, maar een andere context). De operator retourneert maximaal één gematcht element per document.
// Project only the FIRST matching scores element
db.students.find(
{ name: 'Alice' },
{
name: 1,
scores: {
$elemMatch: { subject: 'math' }
}
}
);
// Returns:
// { name: 'Alice', scores: [{ subject: 'math', score: 95, grade: 'A' }] }
// Only the math element is included, english is excluded$elemMatch-projectie versus positionele $
Er zijn twee manieren om één gematcht array-element te projecteren: met de $elemMatch-projectie (in het projectieobject) kun je een andere filter opgeven dan de queryfilter, terwijl de positionele $-operator het eerste element retourneert dat door de queryfilter zelf is gematcht. Gebruik $elemMatch in de projectie wanneer de queryfilter en het element dat je wilt projecteren verschillend zijn.
// $ positional: returns the element matched by the query filter
db.students.find(
{ 'scores.subject': 'math' },
{ 'scores.$': 1 }
);
// $elemMatch projection: different filter from query
db.students.find(
{ name: 'Alice' }, // query doesn't filter scores
{ scores: { $elemMatch: { grade: 'A' } } } // but project only A-grade scores
);Diep geneste subdocumenten in arrays
MongoDB ondersteunt query's op arrays van arrays en diep geneste subdocumenten met behulp van gekoppelde puntnotatie. $elemMatch is echter telkens slechts één niveau diep van toepassing. Voor query's op arrays die in arrays zijn genest, moet je meerdere $elemMatch-operators koppelen of je schema herstructureren om overmatige nesting te voorkomen.
// Document with nested arrays
// { courses: [{ name: 'Math', lessons: [{ id: 1, score: 95 }] }] }
// Query nested array with chained dot notation
db.curriculum.find({ 'courses.lessons.score': { $gt: 90 } });
// More precise with $elemMatch (one level)
db.curriculum.find({
courses: {
$elemMatch: {
name: 'Math',
'lessons.score': { $gt: 90 } // dot notation within $elemMatch
}
}
});Indexering voor $elemMatch-query's
Een multikey-index op het arrayveld ondersteunt $elemMatch-query's. MongoDB gebruikt de index om kandidaatdocumenten te beperken op basis van de geïndexeerde veldwaarden en past vervolgens de volledige $elemMatch-voorwaarde toe om elke kandidaat te bevestigen. Neem voor maximale indexefficiëntie het meest selectieve veld van je $elemMatch-voorwaarde op in de index.
// Index on scores.subject for efficient $elemMatch queries
db.students.createIndex({ 'scores.subject': 1 });
// This $elemMatch query can use the index to find 'math' entries,
// then applies the grade: 'A' condition on those candidates
db.students.find({
scores: {
$elemMatch: {
subject: 'math', // <-- indexed, drives the IXSCAN
grade: 'A' // <-- applied after index lookup
}
}
});$elemMatch met $exists en $type
Je kunt $exists en $type binnen $elemMatch gebruiken om array-elementen te vinden die optionele velden hebben of overeenkomen met een specifiek BSON-type. Dit is handig voor heterogene arrays waarin niet alle elementen dezelfde structuur hebben—iets wat vaak voorkomt bij migraties van oude gegevens of flexibele schema's voor gebeurtenislogboeken.
// Find docs with at least one scores element that has a 'notes' field
db.students.find({
scores: {
$elemMatch: {
notes: { $exists: true }
}
}
});
// Find docs with a scores element where score is a string (data quality check)
db.students.find({
scores: {
$elemMatch: {
score: { $type: 'string' } // should be a number!
}
}
});Praktijkvoorbeeld: e-commercebestellingen
Een praktische toepassing van $elemMatch in e-commerce is het vinden van bestellingen met een bestelregel voor een specifiek product waarvan de hoeveelheid boven een drempelwaarde ligt. Zonder $elemMatch zouden de voorwaarden over verschillende bestelregels worden verspreid en fout-positieven opleveren.
// Find orders containing 'product-123' with qty > 5
db.orders.find({
lineItems: {
$elemMatch: {
productId: 'product-123',
qty: { $gt: 5 }
}
}
});
// Also useful for status-filtered sub-documents:
db.projects.find({
tasks: {
$elemMatch: {
assignee: 'alice',
status: 'in-progress',
priority: { $gte: 3 }
}
}
});Korte controle
Test je begrip van $elemMatch voor het matchen van subdocumenten in arrays.
Samenvatting van de les
In deze les heb je geleerd dat $elemMatch in query's vereist dat alle voorwaarden op één array-element matchen, waarmee het probleem van verspreide velden wordt opgelost, dat $elemMatch in een projectie alleen het eerste gematchte element retourneert en dat multikey-indexen $elemMatch-query's efficiënt ondersteunen. Hierna behandelen we operators voor het bijwerken van arrays.
Leer JavaScript met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 30
- Lessen
- 120
Veelgestelde vragen
Is de les “$elemMatch: subdocumenten in arrays matchen” gratis?
Ja — de volledige tekst van “$elemMatch: subdocumenten in arrays matchen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus MongoDB Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus MongoDB Academy bevat in totaal 4 lessen.
Wat leer ik in “$elemMatch: subdocumenten in arrays matchen”?
U gebruikt $elemMatch om meerdere voorwaarden op één array-element toe te passen en valse positieven door matching van verspreide velden te voorkomen. Je oefent met MongoDB Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met MongoDB Academy te beginnen?
Ervaring vooraf is niet nodig. MongoDB Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “$elemMatch: subdocumenten in arrays matchen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over MongoDB Academy?
Ja. Elke les over MongoDB Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Arrays query'en: $all, $size en element matching
- $elemMatch: subdocumenten in arrays matchen
- Arrays bijwerken: $push, $pull, $pop en $addToSet
- Positionele en gefilterde positionele updates