MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Trova un documento mongodb usando una stringa _id parziale

Il $regex e MongoRegex (ovvero un tipo regex BSON utilizzato in una corrispondenza di uguaglianza) supportano solo la corrispondenza con le stringhe, quindi non puoi usarle direttamente con un ObjectId.

Per quanto riguarda il tuo ultimo esempio di codice, hai tentato di utilizzare $where in un costruttore MongoRegex:

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

MongoRegex il costruttore di 's accetta una singola stringa (ad es. /foo/i ), da cui deriva il motivo e le bandiere. $where deve essere utilizzato come operatore di query di primo livello (non associato a nessun nome di campo). Non seguo quello che stai facendo con $dataProps[$i] , ma supponiamo che tu stia costruendo un singolo $where query in modo che corrisponda alla rappresentazione di stringa di un ObjectId. Il documento di query sarebbe simile al seguente:

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

Nota che sto accedendo a str proprietà qui invece di invocare toString() . Questo perché toString() restituisce effettivamente la rappresentazione della shell di ObjectId. Puoi vederlo controllando la sua fonte nella shell:

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

Inoltre, se stai semplicemente controllando se esiste una sottostringa in _id rappresentazione esadecimale di, potresti voler usare indexOf() (con un != -1 confronto) invece di match() con una regex.

Detto questo, usando $where è generalmente una cattiva idea se non lo stai combinando con criteri di query aggiuntivi che possono usa un indice. Questo perché $where richiama l'interprete JavaScript per ogni documento considerato nel set di risultati. Se lo combini con altri criteri più selettivi, MongoDB può utilizzare un indice e restringere i documenti che deve valutare con $where; tuttavia, stai passando un brutto momento se stai usando $where e la scansione di molti documenti o la scansione di una tabella nel peggiore dei casi.

Probabilmente faresti meglio a creare un secondo campo in ogni documento che contenga la rappresentazione della stringa esadecimale del _id . Quindi, puoi indicizzare quel campo e interrogarlo usando un'espressione regolare. Le query regex non ancorate saranno ancora un po' inefficienti (vedi:uso dell'indice regex nei documenti), ma dovrebbe essere comunque molto più veloce rispetto all'utilizzo di $where .

Questa soluzione (duplicando il _id string) comporterà una certa quantità di spazio di archiviazione aggiuntivo per documento, ma potresti decidere che i 24-30 byte aggiuntivi (carico utile della stringa e un nome di campo breve) siano trascurabili.