2012-04-27 51 views
10

我很新的MongoDB,和我使用它與Java驅動程序一起。我有這個文檔結構:檢索子文檔中的數組作爲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" } 

最後一行對於說明我想要做什麼特別感興趣。每個文檔都是一個房間,並且可能有一個對應於一個子文檔數組的值的「燈光」鍵。從建模的角度來看,我有一個房子,有0-n個房間,每個房間裏有0-n個燈。我理想中的Java做的就是把房間作爲參數的名稱,並返回DBOBJECT的對應燈陣列中的子文檔的集合 - 「讓我所有的燈房‘廚房’」,例如。

到目前爲止,在TDD風格逐漸出發,我已經構造此查詢:

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

我意識到,這是會得到我的房間名字我通過在整個房間的我的文檔」有點卡住從這裏出發的最佳方式是得到我想要的。我正在做什麼甚至可能用一個簡單的查詢,或者我將不得不檢索數組並在代碼中遍歷它,將元素作爲DBObject轉換?我也願意爲我的目的提供一個更好的文檔結構建議 - 我沒有以任何方式與此結構結婚。

對於有些觀點,我很精通SQL和傳統的關係型數據庫,如果在解釋類比方面的幫助。另外,如果我正在屠殺MongoDB術語,請糾正我。提前致謝。

回答

19

所以,你可以做這樣的事情:

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

另外,我建議使用QueryBuilder的在Java驅動程序 - 它比從DBObjects創建查詢更簡潔一點。更好的是,檢查一下Morphia,它是一個使用Java驅動程序的對象映射器。它本身支持其中包含列表的實體模型,並將它們序列化/反序列化爲Mongo,而無需處理DBObject的東西。

+0

感謝您的指點!當我回家時(這是代碼的位置),我會更詳細地看一看。 – 2012-04-27 16:42:39

+1

我喜歡的QueryBuilder的流暢界面的外觀和嗎啡看起來很強大。我想我會堅持你的代碼示例中的方法,直到我知道我在做什麼,然後可能進展到QueryBuilder和Morphia。我總是喜歡完全理解它「老式的方式」,並在走捷徑之前知道我的捷徑。 – 2012-04-28 15:39:13

+0

這不起作用,因爲你不能將BasicDBList強制轉換爲DBObject。 – shreks7 2013-01-11 06:24:32

1

您可以使用一個迭代器領域

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

對於較新的版本,請考慮使用Document。爲了避免未經檢查的強制轉換棉短絨警告,隨着自己寫循環,使用libary的get(final Object key, final Class<T> clazz)方法:

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

其中docClazz是你創造的東西一旦:

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