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

Finden Sie ein mongodb-Dokument mit einer partiellen _id-Zeichenfolge

Der $regex und MongoRegex (d. h. ein BSON-Regex-Typ, der in einem Gleichheitsvergleich verwendet wird) unterstützen nur den Vergleich mit Zeichenfolgen, sodass Sie sie nicht direkt mit einer ObjectId verwenden können.

In Bezug auf Ihr letztes Codebeispiel haben Sie versucht, $where zu verwenden in einem MongoRegex-Konstruktor:

$searchTermsAny[] = array(
    $dataProps[$i] => new MongoRegex( '/'.$sRegex.'/i',
    '$where: "this._id.toString().match(/'.$sRegex.'/i)"' )
);

MongoRegex Der Konstruktor von nimmt einen einzelnen String (z. B. /foo/i ), von dem es das Muster und die Flaggen ableitet. $where soll als Abfrageoperator der obersten Ebene verwendet werden (nicht mit einem Feldnamen verknüpft). Ich verstehe nicht, was Sie mit $dataProps[$i] machen , aber nehmen wir an, Sie würden ein einzelnes $where erstellen Abfrage, um die Zeichenfolgendarstellung einer ObjectId abzugleichen. Das Abfragedokument würde wie folgt aussehen:

{ $where: 'this._id.str.match(/00005/)' }

Beachten Sie, dass ich auf str zugreife Eigenschaft hier, anstatt toString() aufzurufen . Das liegt daran, dass toString() gibt tatsächlich die Shell-Darstellung der ObjectId zurück. Sie können dies sehen, indem Sie die Quelle in der Shell überprüfen:

> x = new ObjectId()
ObjectId("5409ddcfd95d6f6a2eb33e7f")
> x.toString
function (){
    return "ObjectId(" + tojson(this.str) + ")";
}

Auch, wenn Sie einfach prüfen, ob ein Teilstring in der _id vorhanden ist 's Hex-Darstellung können Sie indexOf() (mit einem != -1 Vergleich) statt match() mit einem regulären Ausdruck.

Das heißt, mit $where ist im Allgemeinen eine schlechte Idee, wenn Sie sie nicht mit zusätzlichen Abfragekriterien kombinieren, die möglich sind Verwenden Sie einen Index. Das liegt daran, dass $where ruft den JavaScript-Interpreter für jedes in der Ergebnismenge berücksichtigte Dokument auf. Wenn Sie es mit anderen, selektiveren Kriterien kombinieren, kann MongoDB einen Index verwenden und die Dokumente eingrenzen, die es mit $where auswerten muss; Allerdings steht Ihnen eine schlechte Zeit bevor, wenn Sie $where verwenden und Scannen vieler Dokumente oder im schlimmsten Fall ein Tabellenscan.

Es ist wahrscheinlich besser, in jedem Dokument ein zweites Feld zu erstellen, das die Hex-String-Darstellung der _id enthält . Dann können Sie dieses Feld indizieren und mit einer Regex danach fragen. Die nicht verankerten Regex-Abfragen werden immer noch etwas ineffizient sein (siehe:regex index use in der Dokumentation), aber das sollte immer noch viel schneller sein als die Verwendung von $where .

Diese Lösung (Duplizieren der _id string) etwas zusätzlichen Speicherplatz pro Dokument, aber Sie können entscheiden, dass die zusätzlichen 24-30 Bytes (String-Nutzdaten und ein kurzer Feldname) vernachlässigbar sind.