Bedste praksis for projektioner i API-svar
Design projektioner, der stemmer overens med REST API-svars struktur, så payload-størrelsen reduceres, og følsomme felter beskyttes.
Bedste praksis for projektioner i API-svar er en gratis MongoDB Academy-lektion på CoddyKit. Dette er lektion 4 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.
Tilpas projektioner til API-svarets struktur
Hvert REST- eller GraphQL-endepunkt, som din applikation eksponerer, har en defineret struktur for svaret. Den ideelle MongoDB-projektion returnerer præcis de felter, som denne struktur kræver – hverken flere eller færre. Når din projektion afspejler kontrakten for dit API-svar, undgår du to almindelige antipatterns: overhentning (felter, som endepunktet aldrig sender) og underhentning (felter, der tvinger dig til at udføre en ekstra forespørgsel).
Definér projektionskonstanter
Hvis du hardkoder projektionsobjekter direkte i hver forespørgsel, fører det med tiden til gentagelser og afvigelser. Definér projektionskonstanter sammen med dine dataadgangsfunktioner eller repositories. Hvis strukturen for API-svaret ændrer sig, skal du kun opdatere én konstant i stedet for at lede efter alle forespørgsler i kodebasen.
// projections.js — centralised projection definitions
export const USER_PUBLIC = { _id: 0, username: 1, avatarUrl: 1, createdAt: 1 };
export const USER_PROFILE = { _id: 0, username: 1, email: 1, bio: 1, avatarUrl: 1 };
export const USER_ADMIN = { _id: 0, username: 1, email: 1, role: 1, lastLoginAt: 1, isActive: 1 };
// Usage
const user = await db.collection('users').findOne({ username: 'alice' }, { projection: USER_PROFILE });Returnér aldrig følsomme felter til klienter
Felter som passwordHash, totpSecret, apiKey, ssn og paymentMethodToken må aldrig forekomme i API-svar. Definér en sikker grundprojektion, der som standard udelukker dem, og hent dem kun i interne servicekald, der specifikt har brug for dem. Anvend princippet om mindst mulige rettigheder på datalaget.
// Always exclude sensitive fields from user queries
const SECURE_USER_BASE = {
passwordHash: 0,
totpSecret: 0,
resetToken: 0
};
// All user API responses go through this projection
const user = await db.collection('users').findOne(
{ _id: userId },
{ projection: SECURE_USER_BASE }
);
// Result never contains passwordHash or totpSecretListeendepunkter: Projicér kun opsummeringsfelter
Listeendepunkter (f.eks. GET /products) returnerer typisk en opsummering af hvert element og ikke hele dokumentet. En produktliste viser måske name, price, thumbnailUrl og rating – ikke den fulde description, arrayet specifications eller reviews. En begrænset projektion til listeforespørgsler kan reducere størrelsen på nyttedataene med 90 %, når fulde dokumenter indeholder store tekstmængder eller arrays.
const PRODUCT_SUMMARY = {
_id: 0,
slug: 1,
name: 1,
price: 1,
thumbnailUrl: 1,
rating: 1,
reviewCount: 1
};
// GET /products — lightweight list query
const products = await db.collection('products')
.find({ category: 'electronics', isActive: true })
.projection(PRODUCT_SUMMARY)
.sort({ rating: -1 })
.limit(20)
.toArray();Detaljeendepunkter: Projicér hele objektet
Detaljeendepunkter (f.eks. GET /products/:slug) returnerer en mere omfattende visning af et enkelt dokument. Selv her bør du overveje at udelukke felter, der kun er interne. Du kan projicere alle offentlige felter, men undertrykke intern kostpris, leverandørens kontaktoplysninger eller ID'er fra lagerets kildesystem, som klienter ikke bør se.
const PRODUCT_DETAIL = {
supplierCost: 0, // internal — never expose to clients
warehouseLocation: 0, // internal
syncedFromErpAt: 0 // internal audit field
};
// GET /products/:slug — rich detail query
const product = await db.collection('products').findOne(
{ slug: req.params.slug, isActive: true },
{ projection: PRODUCT_DETAIL }
);Brug også projektioner i aggregeringspipelines
Bedste praksis for projektioner gælder også for aggregeringspipelines. Placér et trin med $project efter $match og før dyre trin som $lookup eller $unwind for at reducere størrelsen på de dokumenter, der bevæger sig gennem pipelinen. Mindre dokumenter i pipelinen betyder mindre brug af hukommelse og CPU på serveren.
db.orders.aggregate([
{ $match: { status: 'shipped', customerId: ObjectId('c1') } },
// Project early to reduce document size before $lookup
{ $project: { total: 1, createdAt: 1, customerId: 1, _id: 0 } },
{
$lookup: {
from: 'customers',
localField: 'customerId',
foreignField: '_id',
as: 'customer'
}
}
]);Projektioner og API-versionering
Når du føjer nye felter til MongoDB-dokumenter, forventer ældre API-klienter dem måske ikke. Ved at bruge strikte inklusionsprojektioner (hvor du angiver præcis de felter, der skal returneres) bliver nye dokumentfelter usynlige for eksisterende API-forbrugere, indtil du udtrykkeligt føjer dem til projektionen. Det giver en naturlig versionsgrænse: Opdatér projektionen, når du opdaterer API-versionen.
// v1 projection — stable contract for existing clients
export const USER_V1 = { _id: 0, username: 1, email: 1 };
// v2 projection — includes new avatarUrl and bio fields
export const USER_V2 = { _id: 0, username: 1, email: 1, avatarUrl: 1, bio: 1 };Test, at projektioner stemmer overens med svarskemaer
Skriv enhedstests, der kontrollerer, at MongoDB-projektionsobjektet stemmer overens med dit API-svarskema (f.eks. et Joi-skema eller en TypeScript-type). Det forhindrer den almindelige fejl, hvor en udvikler føjer et felt til API-svartypen, men glemmer at inkludere det i projektionen – feltet kommer tilbage som undefined i produktion, selv om TypeScript-typekontrollen godkender det.
// Example test asserting projection covers all required response fields
const USER_RESPONSE_FIELDS = ['username', 'email', 'avatarUrl'];
const projection = { username: 1, email: 1, avatarUrl: 1, _id: 0 };
for (const field of USER_RESPONSE_FIELDS) {
if (projection[field] !== 1) {
throw new Error('Projection missing field: ' + field);
}
}
console.log('Projection covers all required response fields');Undgå uoverensstemmelser i projektioner med Mongoose
Mongoose-skemaer med select: false på et felt forhindrer, at feltet vises i et forespørgselsresultat, medmindre det udtrykkeligt inkluderes igen. Kombinér dette med virtuelle felter på skemaniveau for at beregne afledte værdier uden at gemme dem. Tilsammen gør disse værktøjer det muligt at håndhæve en sikker standardprojektion på modelniveau og dermed mindske risikoen for utilsigtet datalækage på grund af en manglende forespørgselsprojektion.
const userSchema = new mongoose.Schema({
username: String,
email: String,
// Excluded from all queries by default — must explicitly use +passwordHash
passwordHash: { type: String, select: false },
// Virtual — computed, not stored, never in DB
get displayName() { return this.username.toUpperCase(); }
});
userSchema.virtual('displayName').get(function() {
return this.username.toUpperCase();
});Overvåg projektionernes effektivitet
Brug explain('executionStats')
nReturned og keysExamined samt docsExamined. Hvis docsExamined er lig med antallet af matchede dokumenter (og ikke nul), er din projektion ikke dækket af et indeks, men den er stadig korrekt – du kan vurdere, om det er vedligeholdelsesomkostningen værd at tilføje et dækkende indeks.const result = await db.collection('users').find(
{ role: 'admin' },
{ projection: { username: 1, email: 1, _id: 0 } }
).explain('executionStats');
console.log('Docs examined:', result.executionStats.totalDocsExamined);
console.log('Keys examined:', result.executionStats.totalKeysExamined);
console.log('Docs returned:', result.executionStats.nReturned);Opsummering: Tjekliste til bedste praksis for projektioner
Brug denne tjekliste til alle MongoDB-forespørgsler i dit API:
- Definér navngivne projektionskonstanter – én pr. endepunkt eller struktur for svaret
- Brug inklusionstilstand til API-svar – angiv præcis det, du har brug for
- Udeluk altid følsomme felter – passwordHash, tokens og interne ID'er
- Brug begrænsede projektioner til listeendepunkter – kun opsummeringer, ingen store brødtekster
- Placér $project tidligt i aggregeringspipelines – reducér de data, der føres videre
Hurtig kontrol
Test din forståelse af begreberne MongoDB og NoSQL Databases fra denne lektion.
Opsummering af lektionen
I denne lektion har du lært, at projektionskonstanter bør defineres pr. API-endepunkt for at forhindre afvigelser, at følsomme felter altid skal udelukkes fra forespørgsler, der er rettet mod klienter, og at en tidlig placering af $project i aggregeringspipelines reducerer belastningen på hukommelsen. Næste emne er sortering og sideinddeling, så du effektivt kan ordne og inddele store resultatsæt.
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 “Bedste praksis for projektioner i API-svar” gratis?
Ja — hele teksten til “Bedste praksis for projektioner i API-svar” 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 “Bedste praksis for projektioner i API-svar”?
Design projektioner, der stemmer overens med REST API-svars struktur, så payload-størrelsen reduceres, og følsomme felter beskyttes. 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 4 af 4.
Hvor lang tid tager lektionen “Bedste praksis for projektioner i API-svar”?
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
- Inkluderings- og ekskluderingsprojektioner
- Projektion af indlejrede felter og arrays
- Arrayprojektionerne $ og $elemMatch
- Bedste praksis for projektioner i API-svar