2016-10-11 106 views
1

比方說,有在MongoDB中的文件,這是這個樣子:MongoDB中自動計算領域

{ 
    "lastDate" : ISODate("2013-14-01T16:38:16.163Z"), 
    "items":[ 
     {"date":ISODate("2013-10-01T16:38:16.163Z")}, 
     {"date":ISODate("2013-11-01T16:38:16.163Z")}, 
     {"date":ISODate("2013-12-01T16:38:16.163Z")}, 
     {"date":ISODate("2013-13-01T16:38:16.163Z")}, 
     {"date":ISODate("2013-14-01T16:38:16.163Z")}   
    ] 
} 

甚至是這樣的:

{ 
    "allAre" : false, 
    "items":[ 
     {"is":true}, 
     {"is":true}, 
     {"is":true}, 
     {"is":false}, 
     {"is":true}   
    ] 
} 

頂級域"lastDate""allAre"應每當數組中的數據發生更改時重新計算。 "lastDate"應該是所有最大的"date""allAre"只有在所有項目都有"is"爲真時才應該等於true。

我應該如何構建我的查詢以實現MongoDB的這種行爲?
在插入時預先計算一些值是否被認爲是一種很好的做法,而不是在獲取請求期間計算它們?

+0

您想根據此條件更新記錄,或者希望在插入時應用此條件。 –

+0

@Himanshusharma這個想法是用''items''在每個操作上更新計算字段(比如''allAre''或''lastDate'''),它可以是'$ pull','$ push'或'$ (更新)'。 – dmigo

+0

@dmigo爲什麼你不能只擴展更新查詢並手動設置屬性?我的意思是因爲你正在做一個「推」,那麼你知道值應該改變。 –

回答

1

MongoDB不能使你所要求的與1查詢。 但你可以在兩步查詢。

首先,推新值放入數組:

db.Test3.findOneAndUpdate(
{_id: ObjectId("58047d0cd63cf401292fe0ad")}, 
{$push: {"items": {"date": ISODate("2013-01-27T16:38:16.163+0000")}}}, 
{returnNewDocument: true}, 
function (err, result) { 

} 
); 

則僅在不到最後更新推「lastDate」。

db.Test3.findOneAndUpdate (
    {_id: ObjectId("58047d0cd63cf401292fe0ad"), "lastDate":{$lt: ISODate("2013-01-25T16:38:16.163+0000")}}, 
    {$set: {"lastDate": ISODate("2013-01-25T16:38:16.163+0000")}}, 
    {returnNewDocument: true}, 
    function (err, result) { 
    } 
); 

需要第二個參數「lastDate」以避免競爭條件。通過這種方式,您可以確定「lastDate」內部確實存在「最高推送日期」。

與您要求的第二個問題相關的您可以遵循相似的策略。僅在{"_id":yourID, "items.is":false)}時更新{"allAre": false}。基本上只有當某個孩子的值爲'假'時才設置爲「假」。如果您沒有找到具有此屬性的文檔,則不要更新任何內容。

// add a new Child to false 
db.Test4.findOneAndUpdate(
{_id: ObjectId("5804813ed63cf401292fe0b0")}, 
{$push: {"items": {"is": false}}}, 
{returnNewDocument: true}, 
function (err, result) { 

} 
); 

// update allAre to false if some child is false 
db.Test4.findOneAndUpdate (
    {_id: ObjectId("5804813ed63cf401292fe0b0"), "items.is": false}, 
    {$set: {"allAre": false}}, 
    {returnNewDocument: true}, 
    function (err, result) { 
    } 
); 
+0

謝謝!它似乎是它。對於第一種情況,甚至可以使用'$ max'。 MongoDB沒有更新選擇功能,這有些令人失望。 – dmigo