MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Länge des String-Feldwerts in mongoDB

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

sucht
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.