2014-01-23 101 views
0

我剛開始使用Mongo Db。以下是我的數據結構。如何在Mongodb中使用Java從子文檔中獲取所需的字段

它有一個skillID數組,每個數組有activeCampaigns,每個activeCampaign有一個callsByTimeZone的數組。

什麼我在SQL方面尋找的是:

Select activeCampaigns.callsByTimeZone.label, 
     activeCampaigns.callsByTimeZone.loaded 
from X 
where skillID=50296 and activeCampaigns.campaign_id= 11371940 
     and activeCampaigns.callsByTimeZone='PT' 

我所期待的輸出是讓

{"label":"PT", "loaded":1 } 

我用的命令是

db.cd.find({ "skillID" : 50296 , "activeCampaigns.campaignId" : 11371940, 
"activeCampaigns.callsByTimeZone.label" :"PT" }, 
{ "activeCampaigns.callsByTimeZone.label" : 1 , 
"activeCampaigns.callsByTimeZone.loaded" : 1 ,"_id" : 0}) 

的輸出我得到的是activeCampaigns.callsByTimeZone下的所有東西,而我期待的只是PT

數據結構:

{ 
    "skillID":50296, 
    "clientID":7419, 
    "voiceID":1, 
    "otherResults":7, 
    "activeCampaigns": 
    [{ 
     "campaignId":11371940, 
     "campaignFileName":"Aaron.name.121.csv", 
     "loaded":259, 
     "callsByTimeZone": 
     [{ 
      "label":"CT", 
      "loaded":6 
     }, 
     { 
      "label":"ET", 
      "loaded":241 
     }, 
     { 
      "label":"PT", 
      "loaded":1 
     }] 
    }] 
} 

我試圖在Java中一樣。

QueryBuilder query = QueryBuilder.start().and("skillID").is(50296) 
        .and("activeCampaigns.campaignId").is(11371940) 
        .and("activeCampaigns.callsByTimeZone.label").is("PT"); 

BasicDBObject fields = new BasicDBObject("activeCampaigns.callsByTimeZone.label",1) 
        .append("activeCampaigns.callsByTimeZone.loaded",1).append("_id", 0); 

DBCursor cursor = coll.find(query.get(), fields); 
String campaignJson = null; 
while(cursor.hasNext()) { 
    DBObject campaignDBO = cursor.next(); 
    campaignJson = campaignDBO.toString(); 
    System.out.println(campaignJson); 
} 

獲得的值是callsByTimeZone數組下的所有值。我目前正在解析獲得的JSON,並且只獲得PT值。有沒有辦法查詢activeCampaigns.callsByTimeZone中的PT字段。

在此先感謝。如果此問題已在論壇中提出,我已經搜索了很多並未能找到合適的解決方案。 在此先感謝。

+0

國際海事組織在Java寫mongodb查詢是真的凝灰岩! – Sikorski

回答

0

從下面的Java代碼中替換while循環似乎給出了「PT」作爲輸出。

`while(cursor.hasNext()) { 
     DBObject campaignDBO = cursor.next(); 
     campaignJson = campaignDBO.get("activeCampaigns").toString(); 
     int labelInt = campaignJson.indexOf("PT", -1); 
     String label = campaignJson.substring(labelInt, labelInt+2); 
     System.out.println(label); 
     }` 
1

有這樣做的幾種方法,但你不應該使用字符串操作(即indexOf),其性能可能是太可怕了。

cursor中的結果是嵌套地圖,代表數據庫中的文檔 - Map是鍵值對的良好Java表示。因此,您可以導航到文檔中需要的位置,而不必將其解析爲字符串。我測試了以下和它的作品對您的測試數據,但如果你的數據不都酷似例如,你可能需要調整它:

while (cursor.hasNext()) { 
    DBObject campaignDBO = cursor.next(); 
    List callsByTimezone = (List) ((DBObject) ((List) campaignDBO.get("activeCampaigns")).get(0)).get("callsByTimeZone"); 
    DBObject valuesThatIWant; 
    for (Object o : callsByTimezone) { 
     DBObject call = (DBObject) o; 
     if (call.get("label").equals("PT")) { 
      valuesThatIWant = call; 
     } 
    } 
} 

取決於你的數據,你可能要添加保護也針對空值。

您正在查找的東西({"label":"PT", "loaded":1 })位於變量valueThatIWant中。請注意,這,也是一個DBOBJECT,即一個地圖,所以如果你想看看裏面有什麼是你需要使用get

valuesThatIWant.get("label"); // will return "PT" 
valuesThatIWant.get("loaded"); // will return 1 

因爲DBOBJECT實際上是一個地圖字符串到對象(即Map<String, Object>)你需要將它出現的值(因此在我的答案中的第一位代碼中的醜) - 用數字,它將取決於數據如何加載到數據庫中,它可能會作爲int或爲雙:

String theValueOfLabel = (String) valuesThatIWant.get("label"); // will return "PT" 
double theValueOfLoaded = (Double) valuesThatIWant.get("loaded"); // will return 1.0 

我還想指出,從我的回答如下:

((List) campaignDBO.get("activeCampaigns")).get(0) 

這假定「activeCampaigns」是一個)的列表,在這種情況b )只有一個條目(我在做get(0))。

您還會注意到,您設置的fields值幾乎完全被忽略,其結果是大部分文檔,而不僅僅是您要求的字段。我敢肯定,你只能定義要查詢返回的頂級域,因此您的代碼:

BasicDBObject fields = new BasicDBObject("activeCampaigns.callsByTimeZone.label",1) 
    .append("activeCampaigns.callsByTimeZone.loaded",1) 
    .append("_id", 0); 

實際上是完全一樣:

BasicDBObject fields = new BasicDBObject("activeCampaigns", 1).append("_id", 0); 

我覺得有些這將幫助你與Java & MongoDB的工作要點是:

  • 當你查詢數據庫,它會回報你的 整個文件到您的查詢相匹配的東西即從「skillID」 向下的所有內容。如果您想選擇要返回的字段,我認爲這些只會是頂級字段。有關更多詳細信息,請參見the documentation
  • 要導航結果,您需要知道返回了DBObject,並且這些實際上是Java中的Map<String, Object> - 您可以使用get導航到正確的節點 ,但您需要將值轉換爲正確的形狀。
+0

非常感謝有關光標如何工作的詳細說明。在發佈這個問題之前,我已經使用BasicDBList完成了相同的工作。通過這樣做,我猜我會實際得到整個callsByTimeZone數組,然後將其解析出來,但我的意圖是編寫一個查詢,它可以直接獲取帶有標籤PT的元素。我想我需要改變模式來達到相同的效果。我在這裏有兩個選項,1.通過創建每個時區的數據作爲activeCampaigns(又名activeCampaigns {callsByTZPacific {},callsByTZEaster {}})等等或 – user3225768

+0

創建另一個集合。2.創建另一個集合callByTimezone – user3225768

+0

Don'不要使用單獨的集合,這會破壞MongoDB的目的;並且您的第一個選項將無法工作,因爲您仍然要檢索所有activeCampaigns - 請記住,「字段」按頂級字段進行過濾。你可能想要看的是[聚合框架](http://docs.mongodb.org/manual/applications/aggregation/) - 這可以讓你更好地控制返回的數據。 – Trisha

相關問題