2014-04-07 10 views
5

voglio fare una query all'interno di un array in MongoDB con regex, le collezioni hanno documenti in questo modo:Regex serie interno in MongoDB

{ 
"_id" : ObjectId("53340d07d6429d27e1284c77"), 
"company" : "New Company", 
"worktypes" : [ 
    { 
     "name" : "Pompas", 
     "works" : [ 
      { 
       "name" : "name 2", 
       "code" : "A00011", 
       "price" : "22,22" 
      }, 
      { 
       "name" : "name 3", 
       "code" : "A00011", 
       "price" : "22,22" 
      }, 
      { 
       "name" : "name 4", 
       "code" : "A00011", 
       "price" : "22,22" 
      }, 
      { 
       "code" : "asdasd", 
       "name" : "asdads", 
       "price" : "22" 
      }, 
      { 
       "code" : "yy", 
       "name" : "yy", 
       "price" : "11" 
      } 
     ] 
    }, 
    { 
     "name" : "name 4", 
     "works" : [ 
      { 
       "code" : "A112", 
       "name" : "Nombre", 
       "price" : "11,2" 
      } 
     ] 
    },   
    { 
     "name" : "ee", 
     works":[ 

      { 
       "code" : "aa", 
       "name" : "aa", 
       "price" : "11" 
      }, 
      { 
       "code" : "A00112", 
       "name" : "Nombre", 
       "price" : "12,22" 
      } 
       ] 
    } 
] 

}

Poi ho bisogno di trovare un documento da parte del il nome dell'azienda e qualsiasi lavoro al suo interno hanno una regex nel codice o nel nome del lavoro. ho questo:

var companyquery = { "company": "New Company"}; 
var regQuery = new RegExp('^A0011.*$', 'i'); 

db.categories.find({$and: [companyquery, 
      {$or: [ 
       {"worktypes.works.$.name": regQuery}, 
       {"worktypes.works.$.code": regQuery} 
      ]}]}) 

Ma non restituisce alcun result..I pensare l'errore è provare a cercare all'interno di array con punti e $ .. Qualche idea?

Edit:

Con questo:

db.categories.find({$and: [{"company":"New Company"}, 
      {$or: [ 
       {"worktypes.works.name": {"$regex": "^A00011$|^a00011$"}}, 
       {"worktypes.works.code": {"$regex": "^A00011$|^a00011$"}} 
      ]}]}) 

questo è il risultato:

{ 
    "_id" : ObjectId("53340d07d6429d27e1284c77"), 
    "company" : "New Company", 
    "worktypes" : [ 
     { 
      "name" : "Pompas", 
      "works" : [ 
       { 
        "name" : "name 2", 
        "code" : "A00011", 
        "price" : "22,22" 
       }, 
       { 
        "code" : "aa", 
        "name" : "aa", 
        "price" : "11" 
       }, 
       { 
        "code" : "A00112", 
        "name" : "Nombre", 
        "price" : "12,22" 
       }, 
       { 
        "code" : "asdasd", 
        "name" : "asdads", 
        "price" : "22" 
       }, 
       { 
        "code" : "yy", 
        "name" : "yy", 
        "price" : "11" 
       } 
      ] 
     }, 
     { 
      "name" : "name 4", 
      "works" : [ 
       { 
        "code" : "A112", 
        "name" : "Nombre", 
        "price" : "11,2" 
       } 
      ] 
     }, 
     { 
      "name" : "Bombillos" 
     }, 
     { 
      "name" : "Pompas" 
     }, 
     { 
      "name" : "Bombillos 2" 
     }, 
     { 
      "name" : "Other type" 
     }, 
     { 
      "name" : "Other new type" 
     } 
    ] 
} 

La regex dont campo i risultati ok ..

+1

Che cos'è 'regexQuery'? – Robin

+0

È una stringa con valore per regex, ho copiato il mio codice dal client nodejs, modifico la mia ricerca. Thanls – colymore

+0

Penso che uno dei problemi è che l'operatore posizionale '$' è un operatore di proiezione/aggiornamento, non un operatore di query, prova qualcosa di più vicino a: '" worktypes.works.name "' piuttosto che '" worktypes.works. $ .name "' – Sammaye

risposta

4

Si utilizza un nativo RegExp oggetto JavaScript per l'espressione regolare, ma per Mongo per elaborare l'espressione regolare deve essere inviato come parte della il documento di query, e questa non è la stessa cosa.

Anche la regex non corrisponde ai valori desiderati. Potrebbe essere ^A0111$ per la corrispondenza esatta, ma la corrispondenza senza distinzione tra maiuscole e minuscole causa un problema che causa una scansione più ampia di un possibile indice. Quindi c'è un modo migliore per scriverlo. Vedi anche il link alla documentazione per i problemi relativi alle corrispondenze senza distinzione tra maiuscole e minuscole.

usare l'operatore $regex invece:

db.categories.find({ 
    "$and": [ 
     {"company":"New Company"}, 
     { "$or": [ 
      { "worktypes.works.name": { "$regex": "^A00011$|^a00011$" }}, 
      { "worktypes.works.code": { "$regex": "^A00011$|^a00011$" }} 
     ]} 
    ] 
}) 

Anche le posizionali $ segnaposti non sono validi per una query, sono utilizzati solo in proiezione o un aggiornamento o l'elemento corrispondente primo trovato dalla query.

Ma il tuo problema attuale sembra essere che stai cercando di ottenere solo gli elementi di un array che "corrispondono" alle tue condizioni. Non si può fare questo con .find() e per questo è necessario utilizzare .aggregate() invece:

db.categories.aggregate([ 

    // Always makes sense to match the actual documents 
    { "$match": { 
     "$and": [ 
      {"company":"New Company"}, 
      { "$or": [ 
       { "worktypes.works.name": { "$regex": "^A00011$|^a00011$" }}, 
       { "worktypes.works.code": { "$regex": "^A00011$|^a00011$" }} 
      ]} 
     ] 
    }}, 

    // Unwind the worktypes array 
    { "$unwind": "$worktypes" }, 

    // Unwind the works array 
    { "$unwind": "$worktypes.works" }, 

    // Then use match to filter only the matching entries 
    { "$match": { 
     "$or": [ 
      { "worktypes.works.name": { "$regex": "^A00011$|^a00011$" } }, 
      { "worktypes.works.code": { "$regex": "^A00011$|^a00011$" } } 
     ] 
    }}, 

    /* Stop */ 
    // If you "really" need the arrays back then include all the following 
    // Otherwise the steps up to here actually got you your results 

    // First put the "works" array back together 
    { "$group": { 
     "_id": { 
      "_id": "$_id", 
      "company": "$company", 
      "workname": "$worktypes.name" 
     }, 
     "works": { "$push": "$worktypes.works" } 
    }}, 

    // Then put the "worktypes" array back 
    { "$group": { 
     "_id": "$_id._id", 
     "company": { "$first": "$_id.company" }, 
     "worktypes": { 
      "$push": { 
       "name": "$_id.workname", 
       "works": "$works" 
      } 
     } 
    }} 
]) 

Quindi cosa .aggregate() fa con tutte queste fasi è rompe gli elementi dell'array in forma normale documento in modo che possano essere filtrati utilizzando il $match operatore. In questo modo, vengono restituiti solo gli elementi che "corrispondono".

Quello che "trova" sta facendo correttamente corrisponde al "documento" che soddisfa le condizioni. Poiché i documenti contengono gli elementi corrispondenti, vengono restituiti. I due principi sono cose molto diverse.

Quando si intende "filtrare" utilizzare aggregato.

+0

Modifica la mia domanda, i risultati non sono spero .. – colymore

+0

@colymore Beh, il documento nel risultato contiene effettivamente elementi che corrispondono all'espressione. g per "filtrare" i risultati della matrice per restituire solo le corrispondenze? Questa è una cosa diversa. –

+0

Sto cercando di ottenere solo i worktypes.works che il suo nome worktype.work.code o il suo nome corrispondano all'espressione regolare e scartare il worktypes.works che non lo è. – colymore

1

penso che ci sia un typo:

la regex dovrebbe essere: ^A00011.*$

tripla 0 invece di doppio 0

+0

Non, stesso risultato. Ho provato con la maggior parte dei codici e dei nomi ma non funziona. – colymore

Problemi correlati