Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

361
Visualizações
Can't use aggregation operator $add to update dates while using Array Filters (MongoDB)

Below is an example of a document in a User collection below.

{
    "_id" : 1,
    "username" : bob,
    "pause" : true,
    "pause_date" : ISODate("2021-07-16T07:13:48.680Z"),
    "learnt_item" : [ 
        {                
            "memorized" : false,
            "character" : "一",
            "next_review" : ISODate("2021-07-20T11:02:44.979Z")
        }, 
        {
            "memorized" : false,
            "character" : "二",
            "next_review" : ISODate("2021-07-20T11:02:44.979Z")
        }, 
        ...
    ]  
}

I need to update all the nested document in "learnt_item" if the "memorized" field is false.

The updates are:

  1. "pause_date" to Null
  2. "pause" to False
  3. Update the ISOdate in "next_review" based on the duration that has passed between "pause_date" and the current time. E.g. pause_date is 4 hours ago, then I want to add 4 hours to the "next_review"

I was able to achieve 1 & 2 using findOneAndUpdate with arrayFilters and also tested no.3 by updating the "next_review" field with a current date to make sure it is updating correctly.

   User.findOneAndUpdate({"_id": req.user._id},
   {$set:{"learnt_item.$[elem].next_review": DateTime.local(),"pause_date": null, "pause": value }},
   {new:true, arrayFilters: [{"elem.memorized": false}]}).exec((err, doc) =>{if (err){res.send(err)} else {res.send(doc)}});

I was thinking of using the $add aggregation operator to increase the date base

"learnt_item.$[elem].next_review": {$add: ["$learnt_item.$[elem].next_review","$pause_date"]}

However, according to the documentation, arrayFilters is not available for updates that use an aggregation pipeline.

Is there another way more efficient way that I can update the ISOdate?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

If you are running MongoDB 4.2 or later you can use a pipeline as the second parameter for the update function, this way you can use the operator $map with $cond to find the entries where the property memorized is equal to false and then add 4 days in milliseconds to the next_review date:

db.collection.update({
  "_id": 1
},
[
  {
    $set: {
      "pause_date": null,
      "pause": false,
      "learnt_item": {
        $map: {
          input: "$learnt_item",
          as: "item",
          in: {
            $cond: [
              {
                $eq: [
                  "$$item.memorized",
                  false
                ]
              },
              {
                memorized: "$$item.memorized",
                character: "$$item.character",
                next_review: {
                  $add: [
                    "$$item.next_review",
                    345600000
                  ]
                }
              },
              "$$item"
            ]
          }
        }
      },
    }
  }
],
{
  new: true,
});

You can check a running example here: https://mongoplayground.net/p/oHh1JWiP8vs

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda