Für MongoDB 3.6 und neuer:
Der $expr
-Operator ermöglicht die Verwendung von Aggregationsausdrücken innerhalb der Abfragesprache, sodass Sie die Verwendung von $strLenCP
nutzen können Operator, um die Länge der Zeichenfolge wie folgt zu überprüfen:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
Für MongoDB 3.4 und neuer:
Sie können das Aggregationsframework auch mit $redact
verwenden Pipeline-Operator, mit dem Sie die logische Bedingung mit $cond
verarbeiten können -Operator und verwendet die speziellen Operationen $$KEEP
um das Dokument zu "behalten", wo die logische Bedingung wahr ist oder $$PRUNE
um das Dokument zu "entfernen", bei dem die Bedingung falsch war.
Dieser Vorgang ähnelt einem $project
Pipeline, die die Felder in der Sammlung auswählt und ein neues Feld erstellt, das das Ergebnis der logischen Bedingungsabfrage enthält, und dann ein nachfolgendes $match
, außer dass $redact
verwendet eine einzige Pipelinestufe, die effizienter ist.
Was die logische Bedingung betrifft, so gibt es String-Aggregationsoperatoren, die Sie verwenden können $strLenCP
Operator, um die Länge der Zeichenfolge zu überprüfen. Wenn die Länge $gt
ist einen bestimmten Wert, dann ist dies ein echter Treffer und das Dokument wird "aufbewahrt". Andernfalls wird es "beschnitten" und verworfen.
Erwägen Sie, die folgende Aggregatoperation auszuführen, die das obige Konzept demonstriert:
db.usercollection.aggregate([
{ "$match": { "name": { "$exists": true } } },
{
"$redact": {
"$cond": [
{ "$gt": [ { "$strLenCP": "$name" }, 40] },
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$limit": 2 }
])
Bei Verwendung von $where
, versuchen Sie Ihre Abfrage ohne die einschließenden Klammern:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
Eine bessere Abfrage wäre, die Existenz des Felds zu prüfen und dann die Länge zu prüfen:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
oder:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB wertet Nicht-$where
aus Abfrageoperationen vor $where
Ausdrücke und Nicht-$where
Abfrageanweisungen können einen Index verwenden. Eine viel bessere Leistung besteht darin, die Länge der Zeichenfolge als ein anderes Feld zu speichern und dann zu indizieren oder danach zu suchen. Anwenden von $where
wird im Vergleich dazu viel langsamer sein. Es wird empfohlen, JavaScript-Ausdrücke und $where
zu verwenden Operator als letzten Ausweg, wenn Sie die Daten nicht anders strukturieren können oder wenn Sie es mit einer kleinen Teilmenge von Daten zu tun haben.
Ein anderer und schnellerer Ansatz, der die Verwendung von $where
vermeidet Operator ist $regex
Operator. Betrachten Sie das folgende Muster, das nach
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Hinweis - Aus den Dokumenten :
Wenn für das Feld ein Index vorhanden ist, gleicht MongoDB den regulären Ausdruck mit den Werten im Index ab, was schneller sein kann als ein Sammlungsscan. Eine weitere Optimierung kann erfolgen, wenn der reguläre Ausdruck ein „Präfixausdruck“ ist, was bedeutet, dass alle potenziellen Übereinstimmungen mit derselben Zeichenfolge beginnen. Dadurch kann MongoDB einen „Bereich“ aus diesem Präfix erstellen und nur mit den Werten aus dem Index abgleichen, die in diesen Bereich fallen.
Ein regulärer Ausdruck ist ein „Präfixausdruck“, wenn er mit einem Caret (^)
beginnt oder ein linker Anker (\A)
, gefolgt von einer Folge einfacher Symbole. Zum Beispiel die Regex /^abc.*/
wird optimiert, indem nur mit den Werten aus dem Index verglichen wird, die mit abc
beginnen .
Zusätzlich wird während /^a/, /^a.*/,
und /^a.*$/
mit äquivalenten Saiten übereinstimmen, haben sie unterschiedliche Leistungsmerkmale. Alle diese Ausdrücke verwenden einen Index, wenn ein geeigneter Index vorhanden ist; jedoch /^a.*/
, und /^a.*$/
sind langsamer. /^a/
kann den Scanvorgang stoppen, nachdem das Präfix gefunden wurde.