2012-04-27 11 views
10

Jestem bardzo nowy w MongoDB i używam go wraz ze sterownikiem Java. Mam tę strukturę dokumentu:Odzyskiwanie pod-dokumentu w tablicy jako DBObject (y)

{ "_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" } 

Tam, gdzie ostatnia linia jest szczególnie interesująca dla zilustrowania tego, co chcę zrobić. Każdy dokument jest pomieszczeniem i może mieć klawisz "świateł" odpowiadający wartości będącej tablicą pod-dokumentów. Z perspektywy modelowania mam dom, w którym są pokoje 0-n, z których każdy ma światła 0-n. Co chcę zrobić w Javie, przyjmij nazwę pokoju jako parametr i zwróć kolekcję DBObject, odpowiadającą pod-dokumentom w tablicy świateł - "get me all lights for room" kitchen "", na przykład .

tej pory przebiega stopniowo w stylu TDD, mam zbudowany to zapytanie.

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

zdaję sobie sprawę, że to dostanie mi cały dokument pokój dla nazwy pokojowej I przechodzą w I” Trochę utknąłem na tym, że najlepszym sposobem na osiągnięcie tego jest uzyskanie tego, czego chcę. Czy to, co robię, jest możliwe z prostym zapytaniem, czy będę musiał pobrać tablicę i iterować ją w kodzie, odrzucając elementy jako DBObject? Jestem także otwarty na sugestie dotyczące lepszej struktury dokumentów dla mojego celu - nie jestem w żaden sposób związany z tą strukturą.

Dla trochę perspektywy, jestem dość dobrze zorientowany w SQL i tradycyjnych relacyjnych bazach danych, jeśli to pomaga pod względem wyjaśniania analogii. Ponadto, jeśli zajmę się terminologią MongoDB, popraw mnie. Z góry dziękuję.

Odpowiedz

19

Tak, można zrobić coś takiego:

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

Ponadto, zalecamy użycie QueryBuilder w sterowniku Java - jest to trochę bardziej zwięzły niż tworzenie zapytań z DBObjects. Nawet lepiej, sprawdź Morphia, która jest programem odwzorowującym obiekty, który używa sterownika Java. Natywnie obsługuje modele encji, które mają w nich listy i serializuje/deserializuje je do Mongo bez potrzeby radzenia sobie z obiektami DBObject.

+0

Dzięki za wskazówki! Przyjrzymy się bardziej szczegółowo, kiedy wrócę do domu (tam jest ten kod). –

+1

Podoba mi się płynny wygląd interfejsu QueryBuilder, a Morphia wygląda bardzo potężnie. Myślę, że będę trzymać się podejścia w twojej próbce kodu, dopóki nie będę wiedział, co robię, a potem prawdopodobnie przejdę do QueryBuilder, a potem Morphia. Zawsze lubię w pełni rozumieć "staroświecki sposób" i wiedzieć, co skracam, zanim przejdę do skrótu. –

+0

To nie działa, ponieważ nie można rzucić BasicDBList do DBObject. – shreks7

1

Można użyć iterator dla pól

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

W przypadku nowszych wersji należy rozważyć użycie urządzenia Document. Aby uniknąć niezaznaczone odlewane i ostrzeżenia puchu, wraz z pisania własnych pętli korzystać z libary za get(final Object key, final Class<T> clazz) metody:

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

gdzie docClazz jest coś, co można stworzyć kiedyś:

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