2012-04-27 14 views
10

que soy muy nuevo en MongoDB, y lo estoy usando junto con el controlador Java. Tengo esta estructura del documento:Recuperar sub-documento matriz como 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" } 

Cuando la última línea es de particular interés para ilustrar lo que quiero hacer. Cada documento es una sala y puede tener una tecla "luces" correspondiente a un valor que es una matriz de subdocumentos. Desde una perspectiva de modelado, tengo una casa, que tiene 0-n habitaciones, cada una de las cuales tiene 0-n luces en ella. Lo que yo quiero hacer en Java es tomar el nombre de la sala como un parámetro y devuelve una colección de dbobject correspondiente a los subdocumentos en la matriz luces - "me consiga todas las luces de la habitación 'cocina'", por ejemplo, .

Hasta el momento, un proceso incremental en estilo TDD, yo he construido esta consulta:.

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; 
} 

Soy consciente de que esto va a conseguirme todo el documento espacio para el nombre de la sala me pase en la Primera' Estoy un poco atascado en lo que la mejor manera de proceder desde aquí es conseguir lo que quiero. ¿Es posible lo que estoy haciendo con una simple consulta, o tendré que recuperar la matriz e iterar a través de ella en el código, fundiendo los elementos como DBObject? También estoy abierto a sugerencias para una mejor estructura de documentos para mi propósito: no estoy casado con esta estructura de ninguna manera.

Por un poco de perspectiva, estoy bastante bien versados ​​en SQL y bases de datos relacionales tradicionales, si eso ayuda en términos de analogías explicativas. Además, si estoy eliminando la terminología de MongoDB, corrígeme. Gracias por adelantado.

Respuesta

19

Por lo tanto, se puede hacer algo como esto:

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); 
    } 
} 

Además, le recomiendo usar el Generador de consultas en el controlador Java - que es un poco más concisa que la creación de consultas de DBObjects. Mejor aún, echa un vistazo a Morphia, que es un mapeador de objetos que usa el controlador de Java. Admite de forma nativa modelos de entidades que tienen listas en ellos, y los serializa/deserializa a Mongo sin necesidad de ocuparse de las cosas de DBObject.

+0

Gracias por los punteros! Lo veré con más detalle cuando llegue a casa (ahí es donde está este código). –

+1

me gusta el aspecto de la interfaz fluida QueryBuilder y Morphia ve muy poderosa. Creo que voy a seguir con el enfoque en la muestra del código aquí hasta que sepa lo que estoy haciendo y luego probablemente progrese a QueryBuilder y luego a Morphia. Siempre me gusta entenderlo completamente "a la vieja usanza" y saber lo que estoy atajando antes de tomar el atajo. –

+0

Esto no funciona ya que no puede lanzar un BasicDBList a un DBObject. – shreks7

1

Se puede utilizar un repetidor para los campos

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

Para versiones más nuevas, considere el uso del Document. Para evitar moldes sin marcar, y las advertencias de borra, además de escribir su propio bucle, utilice el método de la get(final Object key, final Class<T> clazz) libary:

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

donde docClazz es algo que se crea una vez:

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