sql >> Database teknologi >  >> NoSQL >> MongoDB

Strengfeltværdilængde i mongoDB

For MongoDB 3.6 og nyere:

$expr operatoren tillader brugen af ​​aggregeringsudtryk i forespørgselssproget, så du kan udnytte brugen af ​​$strLenCP operatør for at kontrollere længden af ​​strengen som følger:

db.usercollection.find({ 
    "name": { "$exists": true },
    "$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] } 
})

For MongoDB 3.4 og nyere:

Du kan også bruge aggregeringsrammen med $redact pipeline-operatør, der giver dig mulighed for at behandle den logiske betingelse med $cond operatør og bruger de særlige operationer $$KEEP at "beholde" dokumentet, hvor den logiske betingelse er sand eller $$PRUNE for at "fjerne" dokumentet, hvor betingelsen var falsk.

Denne operation ligner at have et $project pipeline, der vælger felterne i samlingen og opretter et nyt felt, der indeholder resultatet fra den logiske betingelsesforespørgsel og derefter en efterfølgende $match , bortset fra at $redact bruger et enkelt pipeline-trin, som er mere effektivt.

Hvad angår den logiske betingelse, er der strengaggregeringsoperatorer, som du kan bruge $strLenCP operatør for at kontrollere længden af ​​strengen. Hvis længden er $gt en specificeret værdi, så er dette et sandt match, og dokumentet "bevares". Ellers "beskæres" og kasseres.

Overvej at køre følgende samlede operation, som demonstrerer ovenstående koncept:

db.usercollection.aggregate([
    { "$match": { "name": { "$exists": true } } },
    {
        "$redact": {
            "$cond": [
                { "$gt": [ { "$strLenCP": "$name" }, 40] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    { "$limit": 2 }
])

Hvis du bruger $where , prøv din forespørgsel uden de omsluttende parenteser:

db.usercollection.find({$where: "this.name.length > 40"}).limit(2);

En bedre forespørgsel ville være at kontrollere feltets eksistens og derefter kontrollere længden:

db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2); 

eller:

db.usercollection.find({name: {$exists: true}, $where: "this.name.length > 
40"}).limit(2); 

MongoDB evaluerer ikke-$where forespørgselsoperationer før $where udtryk og ikke-$where forespørgselsudsagn kan bruge et indeks. En meget bedre ydeevne er at gemme længden af ​​strengen som et andet felt, og så kan du indeksere eller søge på den; anvender $where vil være meget langsommere i forhold til det. Det anbefales at bruge JavaScript-udtryk og $where operatør som en sidste udvej, når du ikke kan strukturere dataene på nogen anden måde, eller når du har at gøre med en lille delmængde af data.

En anderledes og hurtigere tilgang, der undgår brugen af ​​$where operatoren er $regex operatør. Overvej følgende mønster, som søger efter

db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2); 

Bemærk - Fra dokumenterne :

Hvis der findes et indeks for feltet, så matcher MongoDB det regulære udtryk mod værdierne i indekset, hvilket kan være hurtigere end en samlingsscanning. Yderligere optimering kan forekomme, hvis det regulære udtryk er et "præfiksudtryk", hvilket betyder, at alle potentialmatches starter med den samme streng. Dette gør det muligt for MongoDB at konstruere et "interval" fra det præfiks og kun matche de værdier fra indekset, der falder inden for det interval.

Et regulært udtryk er et "præfiksudtryk", hvis det starter med acaret (^) eller et venstre anker (\A) , efterfulgt af en række simple symboler. For eksempel regex /^abc.*/ vil blive optimeret ved kun at matche værdierne fra indekset, der starter med abc .

Derudover mens /^a/, /^a.*/, og /^a.*$/ matcher ækvivalente strenge, de har forskellige præstationskarakteristika. Alle disse udtryk bruger et indeks, hvis der findes et passende indeks; dog /^a.*/ og /^a.*$/ er langsommere. /^a/ kan stoppe scanningen efter at have matchet præfikset.



  1. MongoDB $isArray

  2. Sådan håndteres bruger- og socket-par med node.js + redis

  3. Fremhæv underfelter til topniveau i projektion uden at angive alle nøgler

  4. gemmer tidsserier i redis