2016-10-12 81 views
1

我有一個chats集合巫婆樣本文檔MongoDB的父文檔的搜索結果的基礎上,選擇子文件

{ 
    "_id" : ObjectId("57f95e8e385bb61c5cf2cd18"), 
    //some other fields 
    "messages" : [ 
      { 
        "sender" : "57ec1aaa0ffe16123439d52b", 
        "message" : "Hello!", 
        "sentTime" : "Oct 13, 2016 1:51:31 AM" 
      }, 
      { 
        "sender" : "57ec1aaa0ffe16123439d52b", 
        "message" : "Hello!", 
        "sentTime" : "Oct 13, 2016 1:51:33 AM" 
      } 
    ] 
} 

我想搜索_id場的基礎上,收集和只得到的數據messages sub-document作爲使用MongoDB的java驅動程序的查詢結果,因爲我想使用Gson映射到POJO數組。

所需的輸出:

[ 
     { 
       "sender" : "57ec1aaa0ffe16123439d52b", 
       "message" : "Hello!", 
       "sentTime" : "Oct 13, 2016 1:51:31 AM" 
     }, 
     { 
       "sender" : "57ec1aaa0ffe16123439d52b", 
       "message" : "Hello!", 
       "sentTime" : "Oct 13, 2016 1:51:33 AM" 
     } 
] 

我如何去與這個使用Java驅動程序MongoDB的

回答

0

我們需要指定的查詢和字段列表,在這裏是如何做到這一點的例子:

DB db = //get db 

DBObject object = new BasicDBObject(); 
object.put("_id", new ObjectId("<some id>")); 
DBObject fields = new BasicDBObject(); 
fields.put("messages", 1); 
DBObject result = db.getCollection("test").findOne(object, fields); 
System.out.println(result.get("messages")); 
+0

這是行不通的。它提供了一個帶有id字段和消息字段的文檔。輸出與我在問題中給出的第一個json相同,除了所有其他字段。但我需要它只是像我在問題中發佈的第二個json那樣的子文檔數組。謝謝 – kritya

+0

不可能只獲得一個子文檔部分。我們可以指定像「messages.sender」這樣的字段,但不能直接獲取該部分。此外,您不能同時指定包含和排除字段,並且無論如何我們都會返回ID。所以這是儘可能接近我們可以得到的。 –

+0

那麼我可以根據可以說發送時間來排序消息數組嗎? – kritya

0

也許這有點難看,但它會起作用。

chats.aggregate(Arrays.asList(
    match(eq("_id", <your id here>)), 
    unwind("$messages"), 
    project(fields(excludeId(), 
        computed("sender", "$messages.sender"), 
        computed("message", "$messages.message"), 
        computed("sentTime", "$messages.sentTime"))) 
    )).forEach(printBlock); 

printBlock只是打印出每個文檔(您可以將它們收集到數組中)。

Block<Document> printBlock = new Block<Document>() { 
     @Override 
     public void apply(final Document document) { 
      System.out.println(document.toJson()); 
     } 
    }; 
+0

我相信我不能硬卡那些。對不起,但我沒有使用聚合框架。我無法返回完整的對象嗎?另外,相比之下,聚合的表現如何呢? – kritya

+0

方法聚合將返回一個AggregateIterable 對象,它具有可用於代替forEach的常規迭代方法。就性能而言,在聚合的第一個階段只能匹配一個文檔,而只有這一個文檔將沿着聚合管道進行。所以,在這個特殊情況下,它不應該是一個大問題。 –

+0

我們在那裏做的是這樣的。首先,我們使用「匹配」選擇一個對象,這個單一對象下到聚合流水線,而不是「放鬆」消息 - 這意味着我們的消息數組中的每條消息將被放置在輸出中的單獨文檔中(來自官方doc:「$ unwind管道階段從輸入文檔中解構數組字段以輸出每個元素的文檔」)。而且,從這個結果文檔中,我們只使用消息字段並使用「項目」將它們映射到所需的名稱。 –