2013-06-25 20 views
32

Ho chiesto questo come commento alla domanda another e ho anche inviato un messaggio question su mongodb-user. Nessuna risposta finora, quindi mi sto rivolgendo a una domanda separata.Query array nidificato MongoDB

I documentation stati:

Se il campo contiene una matrice, quindi il $ in operatore seleziona il documenti il ​​cui campo detiene un array che contiene almeno un elemento che corrisponde a un valore nella matrice specificata (ad esempio, , ecc)

sto usando:

mongod --version: 
db version v2.2.2, pdfile version 4.5 
Thu May 30 12:19:12 git version: d1b43b61a5308c4ad0679d34b262c5af9d664267 

mongo --version: 
MongoDB shell version: 2.0.4 

In MongoDB shell:

db.nested.insert({'level1': {'level2': [['item00', 'item01'], ['item10', 'item11']]}}) 

Ecco un elenco di query che dovrebbero funzionare in base alla documentazione, ed i risultati che producono:

Perché non funziona?

> db.nested.findOne({'level1.level2.0': 'item00'}) 
null 

Perché ho bisogno del $ tutto?

> db.nested.findOne({'level1.level2.0': {'$all': ['item00']}}) 
{ 
    "_id" : ObjectId("51a7a4c0909dfd8872f52ed7"), 
    "level1" : { 
     "level2" : [ 
      [ 
       "item00", 
       "item01" 
      ], 
      [ 
       "item10", 
       "item11" 
      ] 
     ] 
    } 
} 

Almeno uno dei seguenti dovrebbe funzionare, giusto?

> db.nested.findOne({'level1.level2.0': {'$in': ['item00']}}) 
null 

> db.nested.findOne({'level1.level2': {'$in': ['item00']}}) 
null 

Qualche idea? Stiamo pensando di abbandonare MongoDB se la sintassi della query non funziona come pubblicizzato.

Grazie!

risposta

6

Utilizzare nidificato elemMatch per cercare livelli nidificati all'interno di array.

Dettagli here.

4

Risposta breve: $ in è per un campo a valore singolo e $ tutto per gli array.

Innanzitutto, db.nested.findOne({'level1.level2.0': 'item00'}) non funziona perché level1.level2.0 contiene un array e si sta tentando di confrontarlo con un singolo valore.

Ora, db.nested.findOne({'level1.level2.0': {'$in': ['item00']}}) non funziona a causa di un motivo simile. $ in è per confrontare un campo con un singolo valore (hai un array) con diversi valori in un array (specificato nella query). $ in sta dicendo: dammi i documenti che hanno questo campo quale valore è incluso in questo array.

$ tutto funziona perché sta dicendo: dammi i documenti che hanno questo campo con diversi valori e tutti i valori di questo array (nella query) sono inclusi in quel campo. (Edited)

potrebbe essere difficile da ottenere, ma guardare a ciò che dice la documentazione per ogni:

$ tutto seleziona i documenti in cui campo detiene un array e contiene tutti gli elementi(e.g. <value>, <value1>, etc.) in l'array.

$ in seleziona i documenti in cui il valore campo è uguale a qualsiasi valore nella matrice specificata (e.g. <value1>, <value2>, etc.)

Speranza che aiuta

+0

Apprezzo il fatto che abbiate il tempo di rispondere, ma sfortunatamente nessuna delle vostre risposte è corretta. Nella pagina "Leggi" del manuale, cercare "La seguente operazione restituisce un cursore a tutti i documenti nella raccolta di bios in cui il campo dell'array contribuisce contiene l'elemento" UNIX ":" Nel collegamento della documentazione nella parte superiore della mia domanda, puoi vedere che $ in dovrebbe funzionare su campi contenenti array. Infine, la tua affermazione "$ tutto funziona perché ..." è errata: non tutti i valori nel campo devono esistere nella query, ma tutti i valori nella query devono esistere nel campo del documento. – dgorur

+0

Grazie per la correzione in "$ tutto funziona perché ...". Quindi stai dicendo che $ in dovrebbe funzionare per gli array e la documentazione lo dice. Ora sono incuriosito. Farò degli esperimenti e vedrò se lo scoprirò. Hai una domanda molto interessante qui! – AntonioOtero

+0

Ho inserito le mie conclusioni in un'altra risposta, spero che ti sia utile. – AntonioOtero

29

Dopo l'esecuzione di alcune query, sono giunto alla conclusione che $ in non funziona per una serie di array.

È possibile utilizzare invece $elemMatch e funzionerà, ma è frustrante che la documentazione di MongoDB non ne avvisa.

Ho creato questo documento:

{ 
     "_id": "51cb12857124a215940cf2d4", 
     "level1": [ 
     [ 
      "item00", 
      "item01" 
     ], 
     [ 
      "item10", 
      "item11" 
     ] 
     ], 
     "items": [ 
     "item20", 
     "item21" 
     ] 
} 

Si noti che le "voci" di campo è un array di stringhe e questa query funziona perfettamente:

db.nested.findOne({"items":{"$in":["item20"]} }) 

Ora, "level1.0" è anche una serie di stringhe, l'unica differenza è che si trova all'interno di un altro array. Questa query dovrebbe funzionare, ma non lo è:

db.nested.findOne({"level1.0":{"$in":["item00"]} }) 

L'unico modo per ottenere il risultato sta usando $ elemMatch:

db.nested.findOne({"level1":{"$elemMatch":{"$in":['item00']}} }) 

Così $elemMatch risolve il problema, ma la vera soluzione è quella di aggiornare la documentazione di MongoDB per affermare che $in non funziona per gli array di array. Forse dovresti inviare una richiesta a 10gen.

+1

Hehe. Ora stai parlando. Ho usato questa soluzione alternativa per alcune query, ma poi: cosa succede se voglio usare $ nin? Lo stesso tipo di comportamento misterioso si presenta e quindi abbiamo iniziato a dubitare di tutti i risultati delle query che stavamo ottenendo. Inoltre, grazie per il termine "array of matrici". – dgorur