2012-02-12 20 views
7

Recentemente ho voluto per filtrare i record che contengono una determinata parola chiave in serie MongoDB, per esempio: ho cinque dischi che contengono parole chiave matrice:MongoDB -Come trovare i record che contengono determinate parole chiave gamma

{a:[1,2]} 
{a:[1,3,8]} 
{a:[1,2,5]} 
{a:[3,5,1]} 
{a:[4,5]} 

Se mi ingresso l'array [1,2,3,5] per la ricerca, quindi voglio ottenere:

{a:[1,2]} 
{a:[1,2,5]} 
{a:[3,5,1]} 

Ognuno di loro è un sub-array di [1,2,3,5].

Qualche idea?

Si prega di non utilizzare una clausola where (quando possibile). Grazie!

+0

Ti piace bisogno di scrivere un filtro personalizzato per questo in js, quindi utilizzare che, come parte della query. http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-JavascriptExpressionsand%7B%7B%24where%7D%7D – Travis

risposta

8

sua semplice da fare in MongoDB, ma la parte più difficile sta preparando i dati per la query. Mi spiego che in oder

semplice parte

È possibile utilizzare $in di trovare gli elementi corrispondenti in una matrice. Proviamo

db.coll.find({a:{$in:[1,2,3,5]}) 

e il risultato è

{ "_id" : ObjectId("4f37c41739ed13aa728e9efb"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f37c42439ed13aa728e9efc"), "a" : [ 1, 3, 8 ] } 
{ "_id" : ObjectId("4f37c42c39ed13aa728e9efd"), "a" : [ 1, 2, 5 ] } 
{ "_id" : ObjectId("4f37c43439ed13aa728e9efe"), "a" : [ 3, 5, 1 ] } 
{ "_id" : ObjectId("4f37c43e39ed13aa728e9eff"), "a" : [ 4, 5 ] } 

Ohh, non è il risultato che ci aspettavamo. Sì perché $ restituisce un articolo se viene trovato un elemento corrispondente (non necessariamente tutto).

Quindi possiamo risolvere questo problema passando gli elementi esatti dell'array a $ in, ad esempio se vogliamo trovare gli elementi che corrispondono a questi array esatti {a: [1,2]} {a: [1,2,5 ]} e {a: [4,5,6]}

db.coll.find({a:{$in:[[1,2],[1,2,5],[4,5,6]]}}) 

otterrete

{ "_id" : ObjectId("4f37c41739ed13aa728e9efb"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f37c42c39ed13aa728e9efd"), "a" : [ 1, 2, 5 ] } 

Questo è tutto

parte più difficile

La parte più difficile è quella di formare tutte le possibili combinazioni della matrice di input [1,2,3,5]. Devi trovare un modo per ottenere tutta la combinazione dell'array sorgente (dal tuo client) e passarlo a $ in.

Ad esempio, questo JS method vi darà tutte le combinazioni di matrice data

var combine = function(a) { 
    var fn = function(n, src, got, all) { 
    if (n == 0) { 
     if (got.length > 0) { 
     all[all.length] = got; 
     } 
     return; 
    } 
    for (var j = 0; j < src.length; j++) { 
     fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all); 
    } 
    return; 
    } 
    var all = []; 
    for (var i=0; i < a.length; i++) { 
    fn(i, a, [], all); 
    } 
    all.push(a); 
    return all; 
} 

>> arr= combine([1,2,3,5]) 

vi darà

[ 
    [ 
     1 
    ], 
    [ 
     2 
    ], 
    [ 
     3 
    ], 
    [ 
     5 
    ], 
    [ 
     1, 
     2 
    ], 
    [ 
     1, 
     3 
    ], 
    [ 
     1, 
     5 
    ], 
    [ 
     2, 
     3 
    ], 
    [ 
     2, 
     5 
    ], 
    [ 
     3, 
     5 
    ], 
    [ 
     1, 
     2, 
     3 
    ], 
    [ 
     1, 
     2, 
     5 
    ], 
    [ 
     1, 
     3, 
     5 
    ], 
    [ 
     2, 
     3, 
     5 
    ], 
    [ 
     1, 
     2, 
     3, 
     5 
    ] 
] 

e si può passare questo arr a $ per trovare tutte le macthing elementi

 db.coll.find({a:{$in:arr}}) 

ti darà

{ "_id" : ObjectId("4f37c41739ed13aa728e9efb"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f37c42c39ed13aa728e9efd"), "a" : [ 1, 2, 5 ] } 

Attendi !, non restituisce ancora i restanti due possibili elementi.

Perché avere una buona occhiata al arr, si trova solo la combinazione. restituisce [1,3,5] ma i dati nel documento sono [3,5,1]. Quindi è chiaro che $in controlla gli articoli in ordine dato (strano!).

Così ora si capisce il suo il veramente duro confronto tra la query MongoDB !. È possibile modificare il codice precedente della combinazione JS precedente per trovare la permutazione possibile per ciascuna combinazione e passarla a mongodb $in. Questo è il trucco.

Dal momento che non ha menzionato alcuna scelta la lingua è difficile raccomandare qualsiasi codice di permutazione. Ma puoi trovare molti approcci diversi in Stackoverflow o googling.

0

Se ho capito, si vuole tornare solo gli oggetti di cui tutti valori di proprietà a sono in argomento di matrice ritrovamento.

Seguendo il suggerimento di Travis' nei commenti, è necessario attenersi alla seguente procedura:

  1. definire una funzione JS per realizzare i vostri desideri (dal momento che non c'è modo nativo di farlo in MongoDB);
  2. Salvare la funzione sul server;
  3. utilizzare la funzione all'interno $where.

Se definire la funzione da utilizzare solo a quella proprietà specifica (a, in questo caso), è possibile saltare il passaggio 2. Tuttavia, dal momento che può essere una funzione utile per altre proprietà di altri documenti, ho definita una funzione più generica, che deve essere salvata sul server da utilizzare AFAIK (anch'io sono nuovo su Mongo).

Qui di seguito ci sono i miei test sul guscio mongo:

<--! language: lang-js --> 

// step 1: defining the function for your specific search 
only = function(property, values) { 
    for(var i in property) if (values.indexOf(property[i]) < 0) return false 
    return true 
} 

// step 2: saving it on the server 
db.system.js.save({ _id : 'only', value : only }) 

// step 3: using the function with $where 
db.coll.find({$where: "only(this.a, [1,2,3,5])"}) 

Con i 5 oggetti che hai fornito sulla questione, si ottiene:

{ "_id" : ObjectId("4f3838f85594f902212eb532"), "a" : [ 1, 2 ] } 
{ "_id" : ObjectId("4f3839075594f902212eb534"), "a" : [ 1, 2, 5 ] } 
{ "_id" : ObjectId("4f38390e5594f902212eb535"), "a" : [ 3, 5, 1 ] } 

Il rovescio della medaglia è la prestazione. See more.

Problemi correlati