MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Trouver un document mongodb en utilisant une chaîne _id partielle

Le $regex et MongoRegex (c'est-à-dire un type de regex BSON utilisé dans une correspondance d'égalité) ne prennent en charge que la correspondance avec des chaînes, vous ne pouvez donc pas les utiliser directement avec un ObjectId.

Concernant votre dernier exemple de code, vous avez tenté d'utiliser $where dans un constructeur MongoRegex :

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

MongoRegex Le constructeur de prend une seule chaîne (par exemple /foo/i ), dont il dérive le motif et les drapeaux. $where est destiné à être utilisé comme opérateur de requête de niveau supérieur (non associé à un nom de champ). Je ne comprends pas ce que vous faites avec $dataProps[$i] , mais supposons que vous construisiez un seul $where requête pour correspondre à la représentation sous forme de chaîne d'un ObjectId. Le document de requête ressemblerait à ceci :

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

Notez que j'accède au str propriété ici au lieu d'invoquer toString() . C'est parce que toString() renvoie en fait la représentation shell de l'ObjectId. Vous pouvez le voir en vérifiant sa source dans le shell :

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

Aussi, si vous vérifiez simplement si une sous-chaîne existe dans le _id , vous pouvez utiliser indexOf() (avec un != -1 comparaison) au lieu de match() avec une expression régulière.

Cela dit, en utilisant $where est généralement une mauvaise idée si vous ne le combinez pas avec des critères de requête supplémentaires qui peuvent utiliser un indice. C'est parce que $where appelle l'interpréteur JavaScript pour chaque document considéré dans le jeu de résultats. Si vous le combinez avec d'autres critères plus sélectifs, MongoDB peut utiliser un index et affiner les documents qu'il doit évaluer avec $where; cependant, vous êtes dans une mauvaise passe si vous utilisez $where et numériser de nombreux documents ou numériser une table dans le pire des cas.

Vous feriez probablement mieux de créer un deuxième champ dans chaque document qui contient la représentation de chaîne hexadécimale du _id . Ensuite, vous pouvez indexer ce champ et l'interroger à l'aide d'une expression régulière. Les requêtes regex non ancrées seront toujours un peu inefficaces (voir :utilisation de l'index regex dans la documentation), mais cela devrait toujours être beaucoup plus rapide que d'utiliser $where .

Cette solution (duplication du _id chaîne) entraînera un stockage supplémentaire par document, mais vous pouvez décider que les 24 à 30 octets supplémentaires (charge utile de chaîne et nom de champ court) sont négligeables.