Operatorer til opdatering af arrays: $push, $pull, $addToSet
Tilføj og fjern elementer fra arrays i dokumenter ved hjælp af målrettede operatorer til array-opdatering.
Operatorer til opdatering af arrays: $push, $pull, $addToSet er en gratis MongoDB Academy-lektion på CoddyKit. Dette er lektion 3 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.
Arrays som førsteklasses værdier
Arrays i MongoDB-dokumenter er almindelige – et produkt har tags, en bruger har roles, og en ordre har items. Når disse arrays skal ændres (tilføje et tag, fjerne en rolle eller føje en ordrelinje til), har du brug for operatorer til arrayopdatering, som ændrer arrayet på stedet i stedet for at erstatte hele dokumentet.
MongoDB har et komplet sæt operatorer til dette formål: $push tilføjer elementer, $pull fjerner elementer efter værdi, $pop fjerner elementer fra enderne, og $addToSet tilføjer kun elementer, hvis de er unikke. Alle disse operationer er atomare – ændringen sker i én enkelt operation på serveren.
$push: Tilføjelse af elementer i et array
Operatoren $push føjer et eller flere elementer til slutningen af et arrayfelt. Hvis feltet ikke findes, opretter $push det som et nyt array, der indeholder det tilføjede element. Hvis feltet findes, men ikke er et array, mislykkes operationen.
Et enkelt $push med en almindelig værdi tilføjer ét element. Hvis du vil tilføje flere elementer i én operation, skal du kombinere $push med modifikatoren $each. $push kontrollerer ikke for dubletter – brug $addToSet, hvis du har brug for unikke værdier.
// Push a single element
db.posts.updateOne(
{ _id: postId },
{ $push: { tags: 'mongodb' } }
);
// tags: ['node', 'backend'] -> ['node', 'backend', 'mongodb']
// Push multiple elements using $each
db.posts.updateOne(
{ _id: postId },
{ $push: { tags: { $each: ['databases', 'nosql'] } } }
);
// tags: ['node'] -> ['node', 'databases', 'nosql']
// Push a sub-document
db.users.updateOne(
{ _id: userId },
{ $push: { addresses: { street: '123 Main St', city: 'Chicago' } } }
);$push med $sort og $slice
Ved at kombinere $push med modifikatorerne $sort og $slice opretter du et sorteret array med en maksimumstørrelse: tilføj nye elementer, sortér arrayet, og begræns det derefter til en maksimal længde. Dette mønster er perfekt til at vedligeholde en liste med de 'bedste N' eller en log med de 'seneste N elementer'.
Modifikatoren $slice begrænser arrayet til de første N elementer efter sortering. Brug negative værdier for de sidste N (f.eks. beholder $slice: -5 de sidste 5 efter sortering). Denne kombination kræver $each, selv hvis du kun tilføjer ét element.
// Maintain a 'top 5 scores' list
db.players.updateOne(
{ _id: playerId },
{
$push: {
topScores: {
$each: [{ score: 9800, date: new Date() }],
$sort: { score: -1 }, // Sort by score descending
$slice: 5 // Keep only top 5
}
}
}
);
// After: topScores always has max 5 entries, highest scores first$pull: Fjernelse af elementer efter værdi
Operatoren $pull fjerner alle elementer fra et array, der matcher en angivet værdi eller betingelse. I modsætning til $pop (som fjerner fra en af enderne) fjerner $pull elementer efter deres værdi, uanset hvor de findes i arrayet.
Du kan angive en simpel værdi (for arrays med primitive værdier) eller en forespørgselsbetingelse (for arrays med underdokumenter). $pull fjerner alle matchende elementer i én atomar operation – du behøver ikke kende elementets position.
// Remove a tag by value
db.posts.updateOne(
{ _id: postId },
{ $pull: { tags: 'outdated' } }
);
// tags: ['mongodb', 'outdated', 'nosql'] -> ['mongodb', 'nosql']
// Removes ALL occurrences of 'outdated'
// Pull with a condition on array of sub-documents
db.orders.updateOne(
{ _id: orderId },
{ $pull: { items: { sku: 'REMOVED-ITEM' } } }
);
// Removes all items where sku = 'REMOVED-ITEM' from the items array$pop: Fjernelse fra enderne af et array
Operatoren $pop fjerner det første eller sidste element i et array, uden at du behøver kende værdien. Brug $pop: { field: 1 } til at fjerne det sidste element og $pop: { field: -1 } til at fjerne det første element.
$pop er nyttig til implementering af køer og dobbeltsidede køer: tilføj bagest med $push, og fjern forrest med $pop: -1. Til køsystemer i produktion bør du dog overveje dedikerede løsninger – dokumentbaserede køer har begrænsninger ved høj samtidighed.
// Remove the last element
db.playlists.updateOne(
{ _id: playlistId },
{ $pop: { songs: 1 } } // 1 = last
);
// songs: ['A', 'B', 'C'] -> ['A', 'B']
// Remove the first element
db.queues.updateOne(
{ _id: queueId },
{ $pop: { items: -1 } } // -1 = first
);
// items: ['task1', 'task2', 'task3'] -> ['task2', 'task3']$addToSet: Indsættelse af unikke elementer
Operatoren $addToSet tilføjer et element til et array kun hvis det ikke allerede findes. Hvis elementet allerede findes, er operationen uden effekt – der tilføjes ingen dublet. Dette er ideelt til vedligeholdelse af sæt med unikke værdier som tags, brugerroller eller kategoritilhørsforhold.
Ligesom $push understøtter $addToSet modifikatoren $each, så du kan tilføje flere unikke elementer i én operation. Hvis feltet ikke findes, opretter operatoren arrayet. BSON-typen og værdien skal matche præcist, for at en dublet kan identificeres.
// Add tag only if not already present
db.posts.updateOne(
{ _id: postId },
{ $addToSet: { tags: 'mongodb' } }
);
// If tags already has 'mongodb': no change
// If not: 'mongodb' is added
// Add multiple unique roles with $each
db.users.updateOne(
{ _id: userId },
{ $addToSet: { roles: { $each: ['viewer', 'commenter'] } } }
);
// Only adds roles that aren't already in the array
// 'viewer' already exists? Skipped. 'commenter' new? Added.$push kontra $addToSet: Sådan vælger du
Valget mellem $push og $addToSet afhænger af, om rækkefølge og dubletter er acceptable:
- Brug $push, når: rækkefølgen er vigtig, dubletter er acceptable (eller forventede), du har brug for sorterede arrays med
$sort/$slice, eller du opbygger en log eller historik, hvor gentagne værdier giver mening - Brug $addToSet, når: du administrerer et sæt af unikke værdier (roller, tilladelser, tags eller abonnementer), og tilføjelse af en eksisterende værdi skal være uden effekt
Vær opmærksom på, at $addToSet skal gennemgå det eksisterende array for at kontrollere for dubletter – for meget store arrays (tusindvis af elementer) kan det være langsomt. Overvej en separat samling til store sæt af unikke værdier.
// $push for ordered history (duplicates ok)
db.users.updateOne(
{ _id: userId },
{ $push: { loginHistory: { at: new Date(), ip: req.ip } } }
);
// Same IP can appear multiple times - that's fine for history
// $addToSet for unique roles (no duplicates)
db.users.updateOne(
{ _id: userId },
{ $addToSet: { roles: 'editor' } }
);
// 'editor' is either added or already there - always uniqueFjernelse af bestemte elementer fra indlejrede arrays
Når dit dokument har et array med underdokumenter, og du skal fjerne et bestemt underdokument ud fra et af dets felter, skal du bruge $pull med et betingelsesudtryk. Betingelsen evalueres for hvert arrayelement, og alle matchende elementer fjernes.
Hvis du vil fjerne flere bestemte værdier på én gang fra et array med primitive værdier, er $pullAll en genvej, der accepterer et array med de værdier, der skal fjernes: { $pullAll: { tags: ['oldTag1', 'oldTag2'] } }. Det svarer til { $pull: { tags: { $in: ['oldTag1', 'oldTag2'] } } }.
// Remove all items in an order for a discontinued product
db.carts.updateOne(
{ _id: cartId },
{
$pull: {
items: { productId: ObjectId('discontinued-id') }
}
}
);
// $pullAll: remove multiple values at once
db.posts.updateOne(
{ _id: postId },
{ $pullAll: { tags: ['spam', 'outdated', 'test'] } }
);
// Removes all occurrences of 'spam', 'outdated', and 'test'Håndtering af arraylængde
Vær forsigtig med ubegrænset vækst af arrays. Arrays, der vokser uden begrænsning (ubegrænsede arrays), får dokumenter til at overskride MongoDBs grænse på 16 MB og forringer ydeevnen, efterhånden som størrelsen på arrayindekset vokser.
Strategier til arrays med begrænset størrelse:
- Brug
$push+$slice: -Ntil kun at beholde de sidste N elementer (rullende vindue) - Fastlæg en forretningsregel: højst 50 varer i kurven, højst 100 historikposter
- Flyt samlinger, der reelt er ubegrænsede, til en separat samling med en reference i stedet for at indlejre dem
// Keep only the last 100 login history entries
db.users.updateOne(
{ _id: userId },
{
$push: {
loginHistory: {
$each: [{ at: new Date(), ip: req.ip }],
$slice: -100 // Keep last 100 (most recent)
}
}
}
);
// loginHistory never exceeds 100 entries
// Oldest entries are automatically droppedPraktisk eksempel: System til at følge brugere
Sociale funktioner som 'følg bruger' og 'stop med at følge bruger' passer naturligt til $addToSet og $pull. Når en bruger følger en anden, tilføjes den fulgte brugers ID til følgerens following-array. Når brugeren stopper med at følge personen, fjernes ID'et. Operatorernes atomare natur betyder, at to samtidige handlinger med at følge eller stoppe med at følge den samme bruger i det samme dokument serialiseres korrekt.
For store sociale grafer (millioner af følgere rammer denne tilgang med indlejrede arrays dokumentgrænsen på 16 MB. Ved stor skala skal du flytte relationerne til en dedikeret follows-samling med felterne followerId og followeeId.
// Follow a user
async function followUser(followerId, followeeId) {
await db.collection('users').updateOne(
{ _id: new ObjectId(followerId) },
{ $addToSet: { following: new ObjectId(followeeId) } }
);
// Optionally: add to followee's followers array too
}
// Unfollow a user
async function unfollowUser(followerId, followeeId) {
await db.collection('users').updateOne(
{ _id: new ObjectId(followerId) },
{ $pull: { following: new ObjectId(followeeId) } }
);
}Den positionelle $-operator i opdateringer
Når du skal opdatere et bestemt element i et array, der matchede din forespørgsel, skal du bruge den positionelle $-operator. I opdateringsdokumentet henviser $ til det første arrayelement, der matchede filterbetingelsen.
Hvis du f.eks. vil markere en bestemt ordrelinje som afsendt, skal du filtrere med { 'items.sku': 'A1' } og derefter opdatere med { : { 'items.$.shipped': true } }. $ fungerer som pladsholder for indekset på det matchede arrayelement. Hvis flere elementer matcher, opdateres kun det første.
// Update a specific array element using positional operator
// Find order containing item sku 'A1', mark it shipped
db.orders.updateOne(
{ _id: orderId, 'items.sku': 'A1' }, // Filter: includes array condition
{ : { 'items.$.shipped': true } } // $: matched array element index
);
// Before: items: [{sku:'A1',shipped:false},{sku:'B2',shipped:false}]
// After: items: [{sku:'A1',shipped:true},{sku:'B2',shipped:false}]Hurtig kontrol
Test din forståelse af begreberne fra denne lektion om MongoDB og NoSQL-databaser.
Opsummering af lektionen
I denne lektion har du lært: $push føjer elementer til et array og understøtter modifikatorerne $each/$sort/$slice til vedligeholdelse af sorterede arrays med begrænset størrelse, f.eks. lister over de bedste N. $pull fjerner alle matchende elementer efter værdi eller betingelse – brug $pullAll til at fjerne flere bestemte værdier på én gang, og $addToSet tilføjer kun et element, hvis det ikke allerede findes – ideelt til vedligeholdelse af unikke sæt som brugerroller, tags og tilladelser uden kontrol af dubletter i applikationskoden. Dernæst ser vi på, hvordan du sikkert sletter dokumenter med deleteOne og deleteMany.
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 “Operatorer til opdatering af arrays: $push, $pull, $addToSet” gratis?
Ja — hele teksten til “Operatorer til opdatering af arrays: $push, $pull, $addToSet” 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 “Operatorer til opdatering af arrays: $push, $pull, $addToSet”?
Tilføj og fjern elementer fra arrays i dokumenter ved hjælp af målrettede operatorer til array-opdatering. 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 3 af 4.
Hvor lang tid tager lektionen “Operatorer til opdatering af arrays: $push, $pull, $addToSet”?
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
- updateOne og updateMany med $set og $unset
- Operatorer til inkrementering, multiplikation og min/maks
- Operatorer til opdatering af arrays: $push, $pull, $addToSet
- Sikker sletning af dokumenter med deleteOne og deleteMany