sql >> Databasteknik >  >> NoSQL >> MongoDB

Strängfältsvärdeslängd i mongoDB

För MongoDB 3.6 och senare:

$expr operatorn tillåter användning av aggregeringsuttryck inom frågespråket, så du kan utnyttja användningen av $strLenCP för att kontrollera längden på strängen enligt följande:

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

För MongoDB 3.4 och senare:

Du kan också använda aggregeringsramverket med $redact pipeline-operatör som låter dig bearbeta det logiska villkoret med $cond operatorn och använder specialoperationerna $$KEEP att "behålla" dokumentet där det logiska villkoret är sant eller $$PRUNE för att "ta bort" dokumentet där villkoret var falskt.

Denna operation liknar att ha ett $project pipeline som väljer fälten i samlingen och skapar ett nytt fält som innehåller resultatet från den logiska villkorsfrågan och sedan en efterföljande $match , förutom att $redact använder ett enda pipelinesteg som är mer effektivt.

När det gäller det logiska villkoret finns det strängaggregationsoperatorer som du kan använda $strLenCP operatör för att kontrollera längden på strängen. Om längden är $gt ett angivet värde, då är detta en sann matchning och dokumentet "behålls". Annars "beskärs" och kasseras den.

Överväg att köra följande sammanställda operation som visar konceptet ovan:

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

Om du använder $where , pröva din fråga utan de omslutande parenteserna:

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

En bättre fråga skulle vara att kontrollera om fältet existerar och sedan kontrollera 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 utvärderar icke-$where frågeoperationer före $where uttryck och icke-$where frågesatser kan använda ett index. En mycket bättre prestanda är att lagra längden på strängen som ett annat fält och sedan kan du indexera eller söka på det; tillämpa $where kommer att vara mycket långsammare jämfört med det. Det rekommenderas att använda JavaScript-uttryck och $where operatör som en sista utväg när du inte kan strukturera data på något annat sätt, eller när du har att göra med en liten delmängd av data.

Ett annat och snabbare tillvägagångssätt som undviker användningen av $where operatorn är $regex operatör. Tänk på följande mönster som söker efter

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

Obs - Från dokumenten :

Om det finns ett index för fältet, matchar MongoDB det reguljära uttrycket mot värdena i indexet, vilket kan vara snabbare än en samlingsskanning. Ytterligare optimering kan ske om det reguljära uttrycket är ett "prefixuttryck", vilket innebär att alla potentiella matchningar börjar med samma sträng. Detta gör att MongoDB kan konstruera ett "intervall" från det prefixet och endast matcha mot de värden från indexet som faller inom det intervallet.

Ett reguljärt uttryck är ett "prefixuttryck" om det börjar med acaret (^) eller ett vänsterankare (\A) , följt av en rad enkla symboler. Till exempel regexet /^abc.*/ kommer att optimeras genom att endast matcha värdena från indexet som börjar med abc .

Dessutom, medan /^a/, /^a.*/, och /^a.*$/ matchar motsvarande strängar, de har olika prestandaegenskaper. Alla dessa uttryck använder ett index om ett lämpligt index finns; dock /^a.*/ , och /^a.*$/ är långsammare. /^a/ kan sluta skanna efter matchning av prefixet.



  1. NestJS:Hur man implementerar sessionsbaserad användarautentisering

  2. Kombinera två ELLER-frågor med AND i Mongoose

  3. Vad är skillnaden mellan spara och infoga i Mongo DB?

  4. MongoNetworkError:kunde inte ansluta till servern [localhost:27017] vid första anslutningen [MongoNetworkError:connect ECONNREFUSED 127.0.0.1:27017]