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
tocondição na consulta - atualize parte, verifique a condição,
- se
fromencontrado emmessagesarray então:$mappara iterar o loop demessagesarray e verifique a condição sefromencontrado então concate assubMessagesatuais array com nova entradasubMessageusando$concatArrays,$mergeObjectspara 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
messagesatuais 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 }
)