2012-04-27 18 views
10

Sono molto nuovo a MongoDB e lo sto utilizzando insieme al driver Java. Ho questa struttura del documento:Recupera il documento secondario nell'array come DBObject (s)

{ "_id" : ObjectId("4f7d2ba6fd5a306d82687d48"), "room" : "Den" } 
{ "_id" : ObjectId("4f7d2baafd5a306d82687d49"), "room" : "Foyer" } 
{ "_id" : ObjectId("4f7d2fdcfd5a306d82687d4a"), "room" : "Master Bedroom" } 
{ "_id" : ObjectId("4f7d301afd5a306d82687d4b"), "room" : "Guest Bedroom" } 
{ "_id" : ObjectId("4f7d2b98fd5a306d82687d47"), "code" : "A", "lights" : [ { "name" : "Overhead", "code" : "1" } ], "room" : "Kitchen" } 

Dove l'ultima riga è di particolare interesse per illustrare cosa voglio fare. Ogni documento è una stanza e può avere una chiave "luci" corrispondente a un valore che è una matrice di sotto-documenti. Dal punto di vista della modellazione, ho una casa, che ha stanze 0-n, ognuna delle quali ha luci 0-n. Quello che voglio fare in Java è prendere il nome della room come parametro e restituire una collezione di DBObject corrispondente ai sotto-documenti dell'array di luci - "prendi tutte le luci per la stanza" kitchen "", per esempio .

Finora, procedendo in modo incrementale in stile TDD, mi hai costruito questa query:.

public static final String ROOM_KEY = "room"; 

public static final String EQUALS_KEY = "$eq"; 

private BasicDBObject buildRoomNameQuery(String roomName) { 

    BasicDBObject myQuery = new BasicDBObject(); 
    myQuery.put(ROOM_KEY, new BasicDBObject(EQUALS_KEY, roomName)); 

    return myQuery; 
} 

mi rendo conto che questo sta per farmi l'intero documento spazio per il nome della stanza mi passa in I' Sono un po 'bloccato su quale sia il modo migliore di procedere da qui per ottenere ciò che voglio. Quello che sto facendo è anche possibile con una semplice query, o dovrò recuperare l'array e scorrere attraverso il codice, gettando gli elementi come DBObject? Sono anche aperto a suggerimenti per una migliore struttura del documento per il mio scopo: non sono sposato con questa struttura in alcun modo.

Per un po 'di prospettiva, sono abbastanza esperto in SQL e nei database relazionali tradizionali, se questo aiuta in termini di analogie esplicative. Inoltre, se sto macellando la terminologia di MongoDB, per favore correggimi. Grazie in anticipo.

risposta

19

Quindi, si può fare qualcosa di simile:

DBCollection coll = db.getCollection("test"); 
BasicDBObject query = new BasicDBObject("room", "Kitchen"); 

// optional, limit the fields to only have the lights field 
BasicDBObject fields = new BasicDBObject("lights",1).append("_id",false); 
DBCursor curs = coll.find(query, fields); 
while(curs.hasNext()) { 
    DBObject o = curs.next(); 

    // shows the whole result document 
    System.out.println(o.toString()); 
    BasicDBList lights = (BasicDBList) o.get("lights"); 

    // shows the lights array -- this is actually a collection of DBObjects 
    System.out.println(lights.toString()); 

    // optional: break it into a native java array 
    BasicDBObject[] lightArr = lights.toArray(new BasicDBObject[0]); 
    for(BasicDBObject dbObj : lightArr) { 
    // shows each item from the lights array 
    System.out.println(dbObj); 
    } 
} 

Inoltre, mi consiglia di utilizzare il QueryBuilder nel driver Java - è un po 'più concisa rispetto alla creazione di query da DBObjects. Ancora meglio, controlla Morphia, che è un object mapper che usa il driver Java. Supporta nativamente i modelli di entità che hanno liste in loro, e li serializza/deserializza a Mongo senza aver bisogno di occuparsi delle cose di DBObject.

+0

Grazie per i puntatori! Darò un'occhiata più in dettaglio quando torno a casa (è qui che si trova questo codice). –

+1

Mi piace l'aspetto fluido dell'interfaccia di QueryBuilder, e Morphia sembra molto potente. Penso che seguirò l'approccio nel tuo codice qui fino a quando non so cosa sto facendo e quindi probabilmente passerò a QueryBuilder e poi a Morphia. Mi piace sempre capirlo pienamente "alla vecchia maniera" e sapere cosa sto tagliando prima di prendere la scorciatoia. –

+0

Questo non funziona poiché non puoi lanciare un BasicDBList su un DBObject. – shreks7

1

È possibile utilizzare un iteratore per i campi

Iterator<DBObject> fields = curs.iterator(); 
      while(fields.hasNext()){ 
       DBObject field = (DBObject) fields.next().get("lights"); 
       System.out.println(field.get("name")); 
      } 
0

Per le versioni più recenti, prendere in considerazione l'uso di Document. Per evitare calchi incontrollati e le avvertenze Linter, insieme con la scrittura del proprio ciclo, utilizzare il metodo del get(final Object key, final Class<T> clazz) libary:

List<Document> comments = posts.get("comments", docClazz) 

dove docClazz è qualcosa che si crea una volta:

final static Class<? extends List> docClazz = new ArrayList<Document().getClass(); 
Problemi correlati