1

我在我的NodeJS應用程序中使用MongoDB本地驅動程序。使用開關盒更新集合中的多個文檔

我在我的數據庫中有一個shifts集合,我需要更新。在我的班次收集樣本文檔

{ 
    "_id" : ObjectId("588425105560bd2ba0065fa4"), 
    "from" : ISODate("2017-01-23T03:20:00.000Z"), 
    "to" : ISODate("2017-01-23T06:20:00.000Z"), 
    "jobId" : ObjectId("586efda790541421b0432897"), 
    "hourlyRate" : 15 
} 

{ 
    "_id" : ObjectId("588425105560bd2ba0065fa5"), 
    "from" : ISODate("2017-01-25T03:20:00.000Z"), 
    "to" : ISODate("2017-01-25T06:20:00.000Z"), 
    "jobId" : ObjectId("586efda790541421b0432897"), 
    "hourlyRate" : 15 
} 

我需要做的是以下 -

更新符合條件的所有文檔的hourlyRate

  • 匹配的jobId(即容易)
  • 集合hourlyRate = 20如果from是一個工作日
  • 集合hourlyRate = 25,如果from是星期六
  • 設置hourlyRate = 30,如果from是星期日

我會想這樣做在單個查詢儘可能。

我到目前爲止的解決方案:

使用開關的情況下,並確定一天的使用$dayOfWeek日期從聚合函數的類型。但是,我無法將開關與updateMany結合使用。

任何幫助,將不勝感激。

回答

1

您可以在您的處置喜歡$switch運行的特殊運營商在聚集管道,其在MongoDB的服務器3.4和上面是新的:

MongoDB的服務器3.4

db.collection('shifts').aggregate([ 
    { 
     "$match": { 
      "jobId": ObjectId(job._id), 
      "from": { "$gte": new Date() } 
     } 
    }, 
    { 
     "$project": { 
      "hourlyRate": { 
       "$switch": { 
        "branches": [ 
         { 
          "case": { 
           "$not": { 
            "$in": [ 
             { "$dayOfWeek": "$from" }, 
             [1, 7] 
            ] 
           } 
          }, 
          "then": 20 
         }, 
         { 
          "case": { 
           "$eq": [ 
            { "$dayOfWeek": "$from" }, 
            7 
           ] 
          }, 
          "then": 25 
         }, 
         { 
          "case": { 
           "$eq": [ 
            { "$dayOfWeek": "$from" }, 
            1 
           ] 
          }, 
          "then": 30 
         } 
        ] 
       } 
      }    
     } 
    }  
], function(err, docs) { 
    var ops = [], 
     counter = 0; 

    docs.forEach(function(doc) { 
     ops.push({ 
      "updateOne": { 
       "filter": { "_id": doc._id }, 
       "update": { "$set": { "hourlyRate": doc.hourlyRate } } 
      } 
     }); 
     counter++; 

     if (counter % 500 === 0) { 
      db.collection('shifts').bulkWrite(ops, function(err, r) { 
       // do something with result 
      }); 
      ops = []; 
     } 
    }) 

    if (counter % 500 !== 0) { 
     db.collection('shifts').bulkWrite(ops, function(err, r) { 
      // do something with result 
     } 
    }  
}); 

的MongoDB服務器3.2

db.collection('shifts').aggregate([ 
    { 
     "$match": { 
      "jobId": ObjectId(job._id), 
      "from": { "$gte": new Date() } 
     } 
    }, 
    { 
     "$project": { 
      "hourlyRate": { 
       "$cond": [ 
        { 
         "$not": { 
          "$setIsSubset": [ 
           [{ "$dayOfWeek": "$from" }], 
           [1, 7] 
          ] 
         } 
        }, 20,         
        { 
         "$cond": [ 
          { "$eq": [ 
           { "$dayOfWeek": "$from" }, 
           7 
          ] }, 
          25, 
          { 
           "$cond": [ 
            { "$eq": [ 
             { "$dayOfWeek": "$from" }, 
             1 
            ] }, 
            30, 
            "$hourlyRate" 
           ] 
          } 
         ] 
        }     
       ]     
      }    
     } 
    } 
], function(err, docs) { 
    var ops = [], 
     counter = 0; 

    docs.forEach(function(doc) { 
     ops.push({ 
      "updateOne": { 
       "filter": { "_id": doc._id }, 
       "update": { "$set": { "hourlyRate": doc.hourlyRate } } 
      } 
     }); 
     counter++; 

     if (counter % 500 === 0) { 
      db.collection('shifts').bulkWrite(ops, function(err, r) { 
       // do something with result 
      }); 
      ops = []; 
     } 
    }) 

    if (counter % 500 !== 0) { 
     db.collection('shifts').bulkWrite(ops, function(err, r) { 
      // do something with result 
     } 
    }  
}) 
+0

真棒男人....像魅力一樣工作..謝謝... – jerry

+0

我只是再次測試它,我意識到執行此查詢會覆蓋班次集合中的所有文檔。例如,如果我使用$ match條件執行上面的查詢jobId = 1,那麼它會爲jobId = 1正確更新所有文檔,但同時所有其他文檔都將被刪除!你能檢查一下嗎?謝謝 – jerry

+0

請檢查我的問題,看看我如何在彙總中使用$匹配。我使用$ addFields版本的答案(用於mongo 3.4的版本) – jerry