2017-06-13 95 views
1

如何刪除作爲此彙總結果返回的所有chunks文檔?

db.getCollection('chunks').aggregate([ 
    { 
     $lookup: 
     { 
      from: "files", 
      localField: "files_id", 
      foreignField: "_id", 
      as: "file" 
     } 
    }, 
    { 
    $match: 
     { 
     "file.uploadDate": 
      { 
      $lt: ISODate("2017-06-10T00:00:00.000Z") 
      } 
     } 
    } 
]) 

我的架構有一個名爲files集合,它包括文件元數據(名稱,uploadDate)和塊,其中包含實際數據(二進制,files_id)

我知道db.collection.deleteMany({})但它僅接受一個匹配過濾器。

我的MongoDB 3.2

回答

2

循環的結果:

var ops = []; 

db.getCollection('chunks').aggregate([ 
    { 
     $lookup: 
     { 
      from: "files", 
      localField: "files_id", 
      foreignField: "_id", 
      as: "file" 
     } 
    }, 
    { 
    $match: 
     { 
     "file.uploadDate": 
      { 
      $lt: ISODate("2017-06-10T00:00:00.000Z") 
      } 
     } 
    } 
]).forEach(doc => { 
    ops = [ 
    ...ops, 
    { "deleteOne": { 
     "filter": { "_id": doc._id } 
    }} 
    ]; 
    if (ops.length >= 1000) { 
    db.getCollection('chunks').bulkWrite(ops); 
    ops = []; 
    } 
}); 

if (ops.length > 0) { 
    db.getCollection('chunks').bulkWrite(ops); 
    ops = []; 
} 

或者在環境中沒有ES6:

var ops = []; 

db.getCollection('chunks').aggregate([ 
    { 
     $lookup: 
     { 
      from: "files", 
      localField: "files_id", 
      foreignField: "_id", 
      as: "file" 
     } 
    }, 
    { 
    $match: 
     { 
     "file.uploadDate": 
      { 
      $lt: ISODate("2017-06-10T00:00:00.000Z") 
      } 
     } 
    } 
]).forEach(function(doc) { 

    ops.push({ "deleteOne": { "filter": { "_id": doc._id } } }); 

    if (ops.length >= 1000) { 
    db.getCollection('chunks').bulkWrite(ops); 
    ops = []; 
    } 
}); 

if (ops.length > 0) { 
    db.getCollection('chunks').bulkWrite(ops); 
    ops = []; 
} 

使用.bulkWrite()那麼你基本上是 「配料」 的請求很多1000.因此,數據庫的實際寫入和響應僅在當時發生,而不是所有en嘗試。

您不能將聚合管道作爲查詢參數提供給一般的.remove**()方法。所以你所做的就是用這樣的動作循環遊標。

+0

謝謝,但我忘了提及我正在使用MongoDB v 3.2,它沒有'=>'運算符。 –

+1

@BabkenVardanyan它應該。它不?你可能想檢查一下你的shell是否不老。或者你實際上是使用Robomongo還是類似的。這只是一個簡單的改變,而不是寫在'function()中。我現在就寫下來。 –

+0

@NeilLunn thanx這麼多,它在這裏幫了很多:) – smknstd

1

你得到的結果彙總後,您可以使用map函數來獲取所有chunkIDS,然後你可以使用db.collection.remove()$in運營商。

var pipeline = [ 
    {$lookup:{ 
     from: "files", 
     localField: "files_id", 
     foreignField: "_id", 
     as: "file" 
    } 
    }, 
    {$match:{ 
     "file.uploadDate": 
     { 
     $lt: ISODate("2017-06-10T00:00:00.000Z") 
     } 
    } 
    } 
]; 

var cursor = db.chunks.aggregate(pipeline); 
var chunkIds = cursor.map(function (chunk) { return chunk._id; }); 
db.chunks.remove({"_id": { "$in": chunkIds }}); 
+0

這裏的問題是有大量的參數發送到'$ in'的請求可以很容易地打破BSON限制。實際上,參數的數量不應超過1000,否則可能會出現問題。在這個網站上還有很多關於人們試圖做同樣的事情的問題。這就是爲什麼我們有批量操作。 –

+0

對於小範圍應用,當用戶知道刪除大小範圍不是很大時(我認爲),並且是的,我同意你的大量數據刪除批量操作,這個查詢是足夠好的 –

+0

我的真正意思是,你實際上並沒有「獲得「任何東西。你「仍然」循環結果,因爲這是'.map()'做的,而且你可能正在填充RAM,因爲你正在構建一個數組。小或大,當你有一個遊標,然後使用它。當我看到這個過程時,如果只有50個結果,那麼仍然只有「一個」請求,並且非常有效。所以實際上,構建一個可以超過1000個項目的數組實際上是成本的。這是需要考慮的。我做到了。 –