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 emmessages
array então:$map
para iterar o loop demessages
array e verifique a condição sefrom
encontrado então concate assubMessages
atuais array com nova entradasubMessage
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
- se
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 }
)