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

Lunghezza del valore del campo stringa in mongoDB

Per MongoDB 3.6 e versioni successive:

Il $expr consente l'uso di espressioni di aggregazione all'interno del linguaggio di query, quindi puoi sfruttare l'uso di $strLenCP operatore per verificare la lunghezza della stringa come segue:

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

Per MongoDB 3.4 e versioni successive:

Puoi anche utilizzare il framework di aggregazione con $redact operatore della pipeline che consente di elaborare la condizione logica con il $cond operatore e utilizza le operazioni speciali $$KEEP per "conservare" il documento in cui la condizione logica è vera o $$PRUNE per "rimuovere" il documento in cui la condizione era falsa.

Questa operazione è simile ad avere un $project pipeline che seleziona i campi nella raccolta e crea un nuovo campo che contiene il risultato della query della condizione logica e quindi un successivo $match , tranne che $redact utilizza una singola fase della pipeline che è più efficiente.

Per quanto riguarda la condizione logica, ci sono operatori di aggregazione di stringhe che puoi utilizzare $strLenCP operatore per verificare la lunghezza della stringa. Se la lunghezza è $gt un valore specificato, quindi questa è una corrispondenza vera e il documento viene "mantenuto". Altrimenti viene "potato" e scartato.

Prendi in considerazione l'esecuzione della seguente operazione di aggregazione che dimostra il concetto di cui sopra:

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

Se si utilizza $where , prova la tua query senza le parentesi quadre:

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

Una query migliore sarebbe quella di verificare l'esistenza del campo e quindi controllare la lunghezza:

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

oppure:

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

MongoDB valuta non $where operazioni di query prima di $where espressioni e non-$where le istruzioni di query possono utilizzare un indice. Una prestazione molto migliore consiste nel memorizzare la lunghezza della stringa come un altro campo e quindi è possibile indicizzarla o cercarla; applicando $where sarà molto più lento rispetto a quello. Si consiglia di utilizzare le espressioni JavaScript e il $where operatore come ultima risorsa quando non puoi strutturare i dati in altro modo o quando hai a che fare con un piccolo sottoinsieme di dati.

Un approccio diverso e più veloce che evita l'uso del $where operatore è il $regex operatore. Considera il seguente modello che cerca

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

Nota - Dai documenti :

Se esiste un indice per il campo, MongoDB confronta l'espressione regolare con i valori nell'indice, il che può essere più veloce della scansione di una raccolta. Un'ulteriore ottimizzazione può verificarsi se l'espressione regolare è una "espressione di prefisso", il che significa che tutte le potenziali corrispondenze iniziano con la stessa stringa. Ciò consente a MongoDB di costruire un "intervallo" da quel prefisso e di confrontare solo i valori dell'indice che rientrano in quell'intervallo.

Un'espressione regolare è un'"espressione di prefisso" se inizia con acaret (^) o un'ancora a sinistra (\A) , seguito da una stringa di simplesymbols. Ad esempio, la regex /^abc.*/ sarà ottimizzato confrontando solo i valori dell'indice che iniziano con abc .

Inoltre, mentre /^a/, /^a.*/, e /^a.*$/ corrispondono a equivalentstrings, hanno caratteristiche prestazionali diverse. Tutte queste espressioni utilizzano un indice se esiste un indice appropriato; tuttavia,/^a.*/ e /^a.*$/ sono più lenti. /^a/ può interrompere la scansione dopo aver trovato la corrispondenza con il prefisso.