2015-01-08 13 views
0

在mongodb的陣列更新值I具有幾個documens的MongoDB中如下:在從Java

{ 
"_id" : ObjectId("54901212f315dce7077204af"), 
"Date" : ISODate("2014-10-20T04:00:00.000Z"), 
"Type" : "Twitter", 
"Entities" : [ 
    { 
     "ID" : 4, 
     "Name" : "test1", 
     "Sentiment" : { 
      "Value" : 20, 
      "Neutral" : 1 
     } 
    }, 
    { 
     "ID" : 5, 
     "Name" : "test5", 
     "Sentiment" : { 
      "Value" : 10, 
      "Neutral" : 1 
     } 
    } 
] 

}

現在我想更新由具有Entities.ID = 4的文件加入(Sentiment.Value + 4)/ 2例如,在更新後,我們有12

我寫了下面的代碼,但我被困在if語句中,你可以看到上面的例子:

DBCollection collectionG; 
    collectionG = db.getCollection("GraphDataCollection"); 
    int entityID = 4; 
    String entityName = "test"; 
    BasicDBObject queryingObject = new BasicDBObject(); 
    queryingObject.put("Entities.ID", entityID); 
    DBCursor cursor = collectionG.find(queryingObject); 

    if (cursor.hasNext()) 
    { 
     BasicDBObject existingDocument = new BasicDBObject("Entities.ID", entityID); 
     //not sure how to update the sentiment.value for entityid=4 
    } 

首先,我認爲我應該首先展開Entities數組以獲得情感價值,但如果我這樣做,那麼我怎樣才能再次使用它們並使用與現在相同的格式更新文檔,但是使用新的情感值?

我也發現了這個鏈接,以及: MongoDB - Update objects in a document's array (nested updating)

,但我不明白它,因爲它不是用Java寫的查詢, 任何人都可以解釋我是如何在Java中做到這一點?

+0

http://stackoverflow.com/a/12103403/1254903 這會有幫助嗎? –

+0

不,因爲它不是一個簡單的更新我需要獲得該entityid的當前情緒值,並將其添加例如4並將其除以2 –

+0

我認爲您問題中描述的文檔與實際結構不同建議去做。沒有字段,例如'sentiment.value',執行所提到的操作我們得到的值爲12.你能檢查文檔結構是否正確? – BatScream

回答

2

你需要做這兩個步驟:

  • 獲取的其中包含一個實體情緒 值4記錄所有_id
  • find期間,只項目 匹配該查詢的實體子文檔,以便我們可以處理它只消耗其 Sentiment.Value。爲此,請使用位置運算符($)。
  • 而不是每次點擊數據庫來更新每個匹配的 記錄,使用Bulk API排隊更新並最終執行它 。

創建批量操作編劇:

BulkWriteOperation bulk = col.initializeUnorderedBulkOperation(); 

找到所有包含在其Entities.ID字段中的值4的記錄。當您將文檔與此查詢進行匹配時,您將得到整個文檔返回。但是我們不想要整個文檔,我們只想要文檔的_id,以便我們可以使用它更新同一文檔,並且文檔中的實體元素的值爲4.可能有其他實體文件,但它們並不重要。因此,爲了只獲得匹配查詢的實體元素,我們使用位置運算符$

DBObject find = new BasicDBObject("Entities.ID",4); 
    DBObject project = new BasicDBObject("Entities.$",1); 
    DBCursor cursor = col.find(find, project); 

上面可能會返回的是以下文檔爲例(因爲我們的示例假定只有一個輸入文檔)。如果您注意到,它只包含一個與我們的查詢匹配的實體元素。

{ 
     "_id" : ObjectId("54901212f315dce7077204af"), 
     "Entities" : [ 
       { 
         "ID" : 4, 
         "Name" : "test1", 
         "Sentiment" : { 
           "Value" : 12, 
           "Neutral" : 1 
         } 
       } 
     ] 
} 

迭代每個記錄排隊的更新:

while(cursor.hasNext()){ 
     BasicDBObject doc = (BasicDBObject)cursor.next(); 
     int curVal = ((BasicDBObject) 
        ((BasicDBObject)((BasicDBList)doc.get("Entities")). 
        get(0)).get("Sentiment")).getInt("Value"); 
     int updatedValue = (curVal+4)/2; 
     DBObject query = new BasicDBObject("_id",doc.get("_id")) 
         .append("Entities.ID",4); 
     DBObject update = new BasicDBObject("$set", 
          new BasicDBObject("Entities.$.Sentiment.Value", 
              updatedValue)); 
     bulk.find(query).update(update); 
    } 

最後更新:

bulk.execute(); 

你需要做一個find()update(),而不是單純的update,因爲目前mongodb不允許引用文檔字段來檢索它的值,修改它並用計算值更新它,以單數形式更新查詢。

+1

非常感謝它的工作,只是一個簡單的問題:你能解釋DBObject project = new BasicDBObject(「Entities。$」,1);更多?例如1是什麼? –

+2

@HamedMinaee - 請看我更新的答案。要了解更多關於位置操作員的信息,請點擊我答案中的'$'符號。(有兩個,都經過兩個) – BatScream

+1

現在我明白了,但爲什麼1爲什麼不是2?我仍然不知道那1點是什麼? –