1

Я использую собственный драйвер MongoDB в приложении NodeJS.Обновление нескольких документов в коллекции с использованием футляра-переключателя

У меня есть коллекция 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

Awesome man .... Работает как шарм .. Спасибо ... – jerry

+0

Я просто тестировал его снова, и я понял, что выполнение этого запроса перезаписывает все документы в коллекции смен. Например, если я выполнил вышеупомянутый запрос с критериями соответствия $ для jobId = 1, то он корректно обновит все документы для jobId = 1, но в то же время удаляются все остальные документы! Можете ли вы проверить это? Спасибо – jerry

+0

Пожалуйста, проверьте мой вопрос, чтобы узнать, как я использую $ match в агрегации. Я использую версию вашего ответа $ addFields (тот, который предназначен для mongo 3.4) – jerry