sql >> Base de Datos >  >> NoSQL >> MongoDB

Encuentre un documento mongodb usando una cadena _id parcial

El $regex y MongoRegex (es decir, un tipo de expresión regular BSON que se usa en una coincidencia de igualdad) solo admite coincidencias con cadenas, por lo que no puede usarlas directamente con un ObjectId.

Con respecto a su último ejemplo de código, intentó usar $where en un constructor MongoRegex:

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

MongoRegex El constructor de toma una sola cadena (por ejemplo, /foo/i ), de donde deriva el patrón y las banderas. $where está destinado a ser utilizado como un operador de consulta de nivel superior (no asociado con ningún nombre de campo). No sigo lo que estás haciendo con $dataProps[$i] , pero supongamos que estuvieras construyendo un solo $where consulta para que coincida con la representación de cadena de un ObjectId. El documento de consulta tendría el siguiente aspecto:

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

Tenga en cuenta que estoy accediendo a str propiedad aquí en lugar de invocar toString() . Eso es porque toString() en realidad devuelve la representación de shell del ObjectId. Puede ver esto comprobando su origen en el shell:

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

Además, si simplemente está comprobando si existe una subcadena en el _id de representación hexadecimal, es posible que desee utilizar indexOf() (con un != -1 comparación) en lugar de match() con una expresión regular.

Dicho esto, usando $where generalmente es una mala idea si no lo combina con criterios de consulta adicionales que pueden utiliza un índice. Esto se debe a que $where invoca al intérprete de JavaScript para cada documento considerado en el conjunto de resultados. Si lo combina con otros criterios más selectivos, MongoDB puede usar un índice y restringir los documentos que necesita evaluar con $where; sin embargo, te encontrarás en un mal momento si estás usando $where y escanear muchos documentos o escanear una tabla en el peor de los casos.

Probablemente sea mejor crear un segundo campo en cada documento que contenga la representación de cadena hexadecimal del _id . Luego, puede indexar ese campo y consultarlo usando una expresión regular. Las consultas de expresiones regulares no ancladas seguirán siendo un poco ineficientes (ver:uso del índice regex en los documentos), pero esto debería ser mucho más rápido que usar $where .

Esta solución (duplicar el _id cadena) incurrirá en algo de almacenamiento adicional por documento, pero puede decidir que los 24-30 bytes adicionales (carga de cadena y un nombre de campo corto) son insignificantes.