MongoDB Academy · leksjon

Regex-spørringer og mønstergjenkjenning

Bruk regulære uttrykk på strengfelt for fleksible søk etter tekstmønstre.

Leksjon 4 av 413 trinn

Regex-spørringer og mønstergjenkjenning er en gratis leksjon i MongoDB Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i MongoDB Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i MongoDB Academy inneholder totalt 4 leksjoner.

Når du trenger mønstergjenkjenning

Noen ganger trenger du å søke etter dokumenter der et strengfelt inneholder, begynner med eller slutter med et bestemt mønster – men du kjenner ikke den nøyaktige verdien. Enkle likhetsfiltre som { name: 'Alice' } finner bare eksakte strenger. Regulære uttrykk (regex) gir deg fleksibel mønstergjenkjenning for strengfelt i MongoDB.

MongoDB støtter regex gjennom operatoren $regex eller ved å sende et JavaScript-regulært uttrykk direkte i et spørringsfilter. Begge fremgangsmåtene fungerer, men har litt ulik syntaks for å angi alternativer som forskjell på store og små bokstaver.

Grunnleggende regex-syntaks i MongoDB

Det finnes to måter å bruke regex i MongoDB-spørringer på:

  • JS-regexliteral: { name: /alice/i } – kortfattet, flagg angis etter den avsluttende skråstreken
  • $regex-operatoren: { name: { $regex: 'alice', $options: 'i' } } – mer omstendelig, men nødvendig når den kombineres med andre operatorer

Begge formene gir identiske resultater. Bruk JS-literalsyntaks for enkle spørringer, og bruk $regex-operatorformen når du må bygge mønsteret dynamisk fra en strengvariabel eller kombinere det med andre operatorer på samme felt.

// JS regex literal - concise
db.users.find({ name: /alice/i });
// 'i' flag = case-insensitive

// $regex operator - equivalent
db.users.find({ name: { $regex: 'alice', $options: 'i' } });

// Dynamic pattern from variable:
const searchTerm = req.query.name;
const escapedTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escape special chars
db.users.find({ name: { $regex: escapedTerm, $options: 'i' } });

Regex-alternativer: i, m, s, x

MongoDB støtter fire regex-flagg:

  • i – Skiller ikke mellom store og små bokstaver: /alice/i finner «Alice», «ALICE» og «alice»
  • m – Flere linjer: ^ og $ samsvarer med begynnelsen eller slutten av hver linje i stedet for hele strengen
  • s – Punkt samsvarer med alt: . samsvarer med alle tegn, inkludert linjeskift
  • x – Utvidet: mellomrom i mønsteret ignoreres (for lesbare mønstre med kommentarer)

Det vanligste flagget er i. Flagget m er nyttig ved søk i tekstfelt med flere linjer, for eksempel blogginnhold. Flere flagg kan kombineres: { $options: 'im' }.

// Case-insensitive search for 'javascript'
db.courses.find({ title: { $regex: 'javascript', $options: 'i' } });
// Matches: 'JavaScript', 'JAVASCRIPT', 'javascript', 'JavaScript Tutorial'

// Multiline match: ^ anchors to start of each line
db.articles.find({ content: { $regex: '^Introduction', $options: 'm' } });
// Matches articles where any line starts with 'Introduction'

// Combined flags
db.posts.find({ body: { $regex: 'mongodb', $options: 'si' } });
// Case-insensitive + dot matches newlines in body

Forankringer: begynner med og slutter med

Bruk regex-forankringer for å samsvare med begynnelsen eller slutten av et strengfelt:

  • ^ forankrer til begynnelsen: /^Admin/ finner strenger som begynner med «Admin»
  • $ forankrer til slutten: /\.pdf$/ finner strenger som slutter med «.pdf»

Et viktig ytelsesfaktum er at et prefiks-regex med cirkumfleks (/^prefix/) KAN bruke en vanlig B-tre-indeks på feltet – MongoDB kan gå direkte til prefikset i indeksen. Dette gjør prefikssøk mye raskere enn søk midt i strengen. Bruk aldri et innledende jokertegn (/.*pattern/ eller /pattern/ uten ^) i en stor samling uten en tekstindeks.

// Prefix match - CAN use index (very efficient)
db.users.find({ username: /^admin/i });
// Matches: 'admin', 'administrator', 'Admin123'
// Uses the index on username (if it exists)

// Suffix match - CANNOT use regular index (slower)
db.files.find({ filename: /\.pdf$/i });
// Matches: 'report.pdf', 'invoice.PDF'
// Must scan all documents - add text index if used frequently

// Mid-string - CANNOT use index
db.products.find({ description: /wireless/i });
// Must scan all documents - use $text index for this

Tegnklasser og kvantorer

Regex gir deg uttrykksfulle byggesteiner for mønstre:

  • . – hvilket som helst tegn (unntatt linjeskift, med mindre flagget s er satt)
  • [abc] – tegnklasse: samsvarer med a, b eller c
  • [a-z] – område: hvilken som helst liten bokstav
  • \d – hvilket som helst siffer (tilsvarer [0-9])
  • \w – hvilket som helst ordtegn ([a-zA-Z0-9_])
  • *, +, ? – null eller flere, én eller flere, null eller én
  • {n}, {n,m} – n forekomster nøyaktig, eller mellom n og m forekomster
// Phone number pattern: +1-XXX-XXX-XXXX or similar
db.users.find({ phone: /^\+?\d{1,3}[-. ]?\(?\d{3}\)?[-. ]?\d{3}[-. ]?\d{4}$/ });

// 6-character alphanumeric codes
db.coupons.find({ code: /^[A-Z0-9]{6}$/ });
// Matches: 'SALE99', 'DISC25', 'FREE01'

// Email basic validation
db.users.find({ email: { $regex: '^[\\w.]+@[\\w.]+\\.[a-z]{2,}$', $options: 'i' } });

Regex kontra tekstindeks: kjenn forskjellen

Regex-spørringer og MongoDBs $text-operator har ulike bruksområder og svært forskjellige ytelsesegenskaper:

  • Regex: samsvarer etter tegnmønster. Fungerer på alle strengfelt, uten behov for en spesialindeks (selv om prefiksforankringer bruker B-tre-indekser). Egner seg for formatvalidering, prefikssøk eller mønstergjenkjenning i små samlinger eller indekserte prefiksspørringer.
  • $text / tekstindeks: fulltekstsøk etter nøkkelord med tokenisering, stemming og filtrering av stoppord. Krever en tekstindeks. Er mye raskere for nøkkelordsøk i store tekstfelt (artikler, beskrivelser og kommentarer).

Bruk aldri /.*keyword.*/i i en stor, uindeksert samling – det utfører en full skanning og kan være tregt.

// Use REGEX for: format matching, prefix searches on indexed field
db.orders.find({ orderNumber: /^ORD-2024/ }); // Prefix - can use index

// Use $text for: keyword search in content fields
// First: create a text index
db.articles.createIndex({ content: 'text', title: 'text' });
// Then: full-text search
db.articles.find({ $text: { $search: 'mongodb performance' } });
// Much faster than /mongodb.*performance/i on large collections

ReDoS: sikkerhetsrisikoen

ReDoS (Regular Expression Denial of Service) er et angrep der en ondsinnet bruker lager en inndatastreng som får et dårlig skrevet regex til å bruke eksponentielt lang tid på evalueringen. Hvis du sender brukerdata direkte inn i et regex uten å escape dem, kan en angriper henge database-spørringen din.

Escape alltid brukerdata før du bruker dem i et regex, ved å erstatte alle spesialtegn for regex (. * + ? ^ $ { } ( ) [ ] | \ ) med de tilsvarende escapede variantene. Mange biblioteker, for eksempel escape-string-regexp i Node.js, gjør dette automatisk. Foretrekk dessuten $text fremfor rå regex for søk som er synlige for brukere.

// DANGEROUS: raw user input in regex (ReDoS risk)
const input = req.query.search; // User controls this
db.products.find({ name: { $regex: input } }); // NEVER DO THIS

// SAFE: escape user input before using in regex
function escapeRegex(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
const safeInput = escapeRegex(req.query.search);
db.products.find({ name: { $regex: safeInput, $options: 'i' } });

// BETTER: Use $text for user-facing search
db.products.find({ $text: { $search: req.query.search } });

Regex på matrisefelt

Når du bruker et regex på et matrisefelt, kontrollerer MongoDB om et hvilket som helst element i matrisen samsvarer med mønsteret – den samme innebyggingssemantikken som ved likhetsspørringer på matriser. Dette lar deg søke gjennom matriser med tagger, kategorier eller andre strenger uten en spesialoperator.

Et dokument med tags: ['node.js', 'mongodb', 'backend'] ville for eksempel blitt returnert av { tags: /^mongo/ } fordi «mongodb» begynner med «mongo». Regex-uttrykket brukes på hvert element separat.

// Document: { tags: ['node.js', 'mongodb', 'backend-dev'] }

// Find products where any tag starts with 'mongo'
db.products.find({ tags: /^mongo/i });
// Returns the document (tags contains 'mongodb')

// Find articles where any category contains 'tech'
db.articles.find({ categories: /tech/i });
// Matches: categories containing 'technology', 'tech-news', 'fintech'

// Index on array field improves regex prefix searches
db.articles.createIndex({ categories: 1 });

Praktisk søkeeksempel

En typisk søkefunksjon for netthandel kombinerer regex med andre filtre for å gi et kontekstuelt produktsøk som ikke skiller mellom store og små bokstaver. Spørringen finner produktnavn som inneholder søkeordet hvor som helst i strengen, filtrert etter kategori og lagerstatus.

For små kataloger (under 50 000 produkter) er regex-søk akseptabelt. For større kataloger eller søk i fullstendige beskrivelser gir Atlas Search (basert på Lucene) bedre relevansrangering, stemming og ytelse.

// Search endpoint: GET /products?q=wireless&category=Electronics
app.get('/products', async (req, res) => {
  const filter = { stock: { $gt: 0 } };

  if (req.query.q) {
    const escaped = req.query.q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    filter.name = { $regex: escaped, $options: 'i' };
  }
  if (req.query.category) {
    filter.category = req.query.category;
  }

  const products = await db.collection('products')
    .find(filter)
    .project({ name: 1, price: 1, _id: 1 })
    .limit(50)
    .toArray();

  res.json(products);
});

Sammendrag av regex-ytelse

Viktige regler for regex-ytelse i MongoDB:

  • Prefiks med ^ (/^prefix/): Kan bruke en B-tre-indeks. Best ytelse for regex.
  • Prefiks som skiller mellom store og små bokstaver (/^prefix/): Utnytter indeksrekkefølgen fullt ut.
  • Prefiks som ikke skiller mellom store og små bokstaver (/^prefix/i): Bruker indeksen delvis, men er fortsatt mye raskere enn uten forankring.
  • Inneholder uten forankring (/pattern/): Full skanning av samlingen – bruk heller en tekstindeks.
  • Endelse (/pattern$/): Full skanning av samlingen eller tekstindeks.

Når du er usikker, kan du teste med explain('executionStats') og se etter IXSCAN kontra COLLSCAN.

// Check if regex query uses an index
db.users.find({ username: /^alice/i })
  .explain('executionStats');
// winningPlan.stage should be 'IXSCAN' if username is indexed

// Compare index scan vs collection scan:
// /^alice/ on indexed field: totalDocsExamined ~= nReturned (efficient)
// /alice/  on any field: totalDocsExamined = all documents (slow!)

Teste regex-mønstre før distribusjon

Før du kjører en regex-spørring mot en produksjonssamling, bør du teste mønsteret mot eksempel­dokumenter for å bekrefte at det finner det du ønsker, og ikke finner det du ikke ønsker. MongoDB-skallet lar deg teste raskt med en liten limit(), og JavaScripts String.prototype.test() eller regex-literals lar deg validere mønstre i Node.js før du bygger dem inn i spørringer.

Kontroller også ytelsen med explain(): Et regex som krever full skanning av samlingen, bør konverteres til en tekstspørring, eller du bør ta hensyn til størrelsen på samlingen. For nye samlinger bør du planlegge med søkekravene i tankene – legg til tekstindekser fra starten i stedet for å ettermontere dem.

// Step 1: Test regex in Node.js before using in query
const pattern = /^wireless/i;
const testStrings = ['Wireless Headphones', 'wireless mouse', 'Wired Keyboard'];
testStrings.forEach(s => console.log(s, '=>', pattern.test(s)));
// 'Wireless Headphones' => true
// 'wireless mouse' => true
// 'Wired Keyboard' => false

// Step 2: Test on production with limit
db.products.find({ name: /^wireless/i }).limit(5);

// Step 3: Check performance
db.products.find({ name: /^wireless/i }).explain('executionStats');

Rask sjekk

Test forståelsen din av begrepene i MongoDB og NoSQL-databaser fra denne leksjonen.

Oppsummering av leksjonen

I denne leksjonen lærte du: regex-spørringer bruker /pattern/flags eller $regex-operatoren for fleksibel mønstergjenkjenning i strenger – det viktigste flagget er i for å ignorere forskjeller mellom store og små bokstaver, prefiksforankrede regex-uttrykk (/^prefix/) kan bruke B-tre-indekser for effektive oppslag, mens mønstre midt i strengen krever full skanning, og du må alltid escape brukerdata før du setter dem inn i et regex for å forhindre ReDoS-angrep – eller enda bedre, bruke $text-operatoren med en tekstindeks for brukervendte søk. Neste gang går vi videre til oppdatering av dokumenter med $set, $unset og andre oppdateringsoperatorer.

Gratis å komme i gang

Lær deg JavaScript med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
30
Leksjoner
120

Ofte stilte spørsmål

Er leksjonen «Regex-spørringer og mønstergjenkjenning» gratis?

Ja – hele teksten i «Regex-spørringer og mønstergjenkjenning» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av MongoDB Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i MongoDB Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Regex-spørringer og mønstergjenkjenning»?

Bruk regulære uttrykk på strengfelt for fleksible søk etter tekstmønstre. Du øver på MongoDB Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med MongoDB Academy?

Ingen tidligere erfaring er nødvendig. MongoDB Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «Regex-spørringer og mønstergjenkjenning»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne MongoDB Academy-leksjonen?

Ja. Alle MongoDB Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Sammenligningsoperatorer: $eq, $gt, $lt, $in
  2. Logiske operatorer: $and, $or, $nor, $not
  3. Elementoperatorer og typesjekker
  4. Regex-spørringer og mønstergjenkjenning
← Tilbake til MongoDB Academy