2014-10-17 15 views
9

Dire Ho una collezione con questi campi:Trova partita su array di RegEx in MongoDB Collection

{ 
    "category" : "ONE", 
    "data": [ 
     { 
      "regex": "/^[0-9]{2}$/", 
      "type" : "TYPE1" 
     }, 
     { 
      "regex": "/^[a-z]{3}$/", 
      "type" : "TYPE2" 
     } 
     // etc 
    ] 
} 

Quindi il mio ingresso è "abc" quindi mi piacerebbe ottenere il tipo corrispondente (o migliore corrispondenza, anche se inizialmente presumo che i RegEx siano esclusivi). C'è un modo possibile per ottenere questo con prestazioni decenti? (Che sarebbe escludendo l'iterazione su ogni elemento dell'array RegEx)

Si prega di notare lo schema potrebbe essere ri-arrangiati, se possibile, in quanto questo progetto è ancora in fase di progettazione. Quindi le alternative sarebbero benvenute.

Ogni categoria può avere circa 100 - 150 RegExes. Ho in programma di avere circa 300 categorie. Ma so che i tipi si escludono a vicenda.

esempio del mondo reale per una categoria:

type1=^34[0-9]{4}$, 
type2=^54[0-9]{4}$, 
type3=^39[0-9]{4}$, 
type4=^1[5-9]{2}$, 
type5=^2[4-9]{2,3}$ 
+0

Come molti modelli o tipi si pensa che si avrà: 10, 100, 1000, Di Più? –

+0

In media direi circa 100 - 150 per ogni categoria. – Dan

+0

ma devi solo testare una categoria per stringa di input? –

risposta

2

Descrivendo la RegEx (Divide et Impera) sarebbe di grande aiuto nel limitare il numero di documenti necessari da trattare.

Alcune idee in questa direzione:

  • RegEx accettare lunghezza (fissa, min, max)
  • POSIX classi di personaggi stile ([:alpha:], [:digit:], [:alnum:], etc.)
  • Albero come Struttura del documento (umm)

Attuazione ciascuno di questi sarebbe aggiungere alla complessità (codice e/o immissione manuale) per inserimento e anche un sovraccarico per descrivere la searchterm prima query.

Avere tipi escludono a vicenda in una categoria semplifica le cose, ma per quanto riguarda tra le categorie?

300 categorie @ 100-150 espressioni regolari/category =>30k a 45k espressioni regolari

... un po 'sarebbe sicuramente esatte duplicati se non la maggior parte di loro.

In questo approccio cercherò di ridurre al minimo il numero totale di documenti da memorizzare/interrogati in uno stile invertito rispetto allo schema "proposto" iniziale.
Nota: includeva solo le lunghezze di stringa in questa demo per restringimento, questo può venire naturalmente per l'immissione manuale in quanto potrebbe rafforzare un controllo visivo sul RegEx

Considerate rewiting la Collezione regexes con i documenti come segue:

{ 
    "max_length": NumberLong(2), 
    "min_length": NumberLong(2), 
    "regex": "^[0-9][2]$", 
    "types": [ 
    "ONE/TYPE1", 
    "NINE/TYPE6" 
    ] 
}, 
{ 
    "max_length": NumberLong(4), 
    "min_length": NumberLong(3), 
    "regex": "^2[4-9][2,3]$", 
    "types": [ 
    "ONE/TYPE5", 
    "TWO/TYPE2", 
    "SIX/TYPE8" 
    ] 
}, 
{ 
    "max_length": NumberLong(6), 
    "min_length": NumberLong(6), 
    "regex": "^39[0-9][4]$", 
    "types": [ 
    "ONE/TYPE3", 
    "SIX/TYPE2" 
    ] 
}, 
{ 
    "max_length": NumberLong(3), 
    "min_length": NumberLong(3), 
    "regex": "^[a-z][3]$", 
    "types": [ 
    "ONE/TYPE2" 
    ] 
} 

.. ogni RegEx unico come il proprio documento, avendo le categorie a cui appartiene (estendibile a molteplici tipi per ogni categoria)

Codice aggregazione Demo:

function() { 

    match=null; 
    query='abc'; 

    db.regexes.aggregate(
    {$match: { 
     max_length: {$gte: query.length}, 
     min_length: {$lte: query.length}, 
     types: /^ONE\// 
     } 
    }, 
    {$project: { 
     regex: 1, 
     types: 1, 
     _id:0 
     } 
    } 
    ).result.some(function(re){ 
     if (query.match(new RegExp(re.regex))) return match=re.types; 
    }); 
    return match; 
} 

ritorno per 'abc' query:

[ 
    "ONE/TYPE2" 
] 

questo verrà eseguito contro solo questi due documenti:

{ 
    "regex": "^2[4-9][2,3]$", 
    "types": [ 
    "ONE/TYPE5", 
    "TWO/TYPE2", 
    "SIX/TYPE8" 
    ] 
}, 
{ 
    "regex": "^[a-z][3]$", 
    "types": [ 
    "ONE/TYPE2" 
    ] 
} 

ridotto dalla lunghezza 3 e avendo la categoria ONE.

Potrebbe essere ridotto ulteriormente implementando POSIX descrittori (facile da confrontare con il searchterm ma devono ingresso 2 espressioni regolari nel DB)

0

ricerca in ampiezza. Se il tuo input inizia con una lettera puoi buttare via il tipo 1, se contiene anche un numero puoi buttare via categorie esclusive (solo numeri o solo lettere) e se contiene anche un simbolo quindi mantieni solo una manciata di tipi contenenti tutti e tre. Quindi segui i consigli sopra riportati per le categorie rimanenti. In un certo senso, imposta casi per tipi di input e casi d'uso per un numero selezionato di "tipi di espressioni regolari" per cercare in basso a destra.

Oppure è possibile creare un modello regex basato sull'input e confrontarlo con l'elenco di modelli regex esistenti come stringa per ottenere il tipo. In questo modo devi solo spendere risorse analizzando l'input per costruire la regex per esso.