MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

$ push com posicional ($) em falhas de upsert


Upsert não funcionará em documentos aninhados na consulta de atualização,

Você pode tentar uma atualização complexa com uma consulta de agregação para lidar com seus casos se quiser fazer isso em uma única consulta,

Vamos pegar um exemplo de entrada e ver um exemplo em termos de caso,

Caso 1: Se especificado messages.from campo existe em messages variedade
var to = "111";
var from = "222";
var subMessage = {
  message: "test",
  date: ISODate("2021-06-29T15:57:53.975Z")
};

Playground

Caso 2: Se messages.from campo não existe na matriz
var to = "111";
var from = "333";
var subMessage = {
  message: "test2",
  date: ISODate("2021-06-29T15:57:53.975Z")
};

Playground

Caso 3: Se o documento não existir
var to = "111";
var from = "333";
var subMessage = {
  message: "test2",
  date: ISODate("2021-06-29T15:57:53.975Z")
};

Playground

Sua consulta final seria,
  • marque apenas to condição na consulta
  • atualize parte, verifique a condição,
    • se from encontrado em messages array então:
      • $map para iterar o loop de messages array e verifique a condição se from encontrado então concate as subMessages atuais array com nova entrada subMessage usando $concatArrays , $mergeObjects para mesclar o objeto atual com o objeto atualizado
    • senão de não encontrado então concate o novo array de objetos de mensagem nas messages atuais matriz usando $cocnatArrays
  • upsert: true , para inserir um novo documento se não for encontrado na coleção
db.pendingMessages.updateOne(
  { to: to },
  [{
    $set: {
      messages: {
        $cond: [
          { $in: [from, { $ifNull: ["$messages.from", []] }] },
          {
            $map: {
              input: "$messages",
              in: {
                $mergeObjects: [
                  "$$this",
                  {
                    subMessages: {
                      $cond: [
                        { $eq: ["$$this.from", from] },
                        {
                          $concatArrays: ["$$this.subMessages", [subMessage]]
                        },
                        "$$this.subMessages"
                      ]
                    }
                  }
                ]
              }
            }
          },
          {
            $concatArrays: [
              { $ifNull: ["$messages", []] },
              [
                {
                  from: from,
                  subMessages: [subMessage]
                }
              ]
            ]
          }
        ]
      }
    }
  }],
  { upsert: true }
)