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.