Upsert non funzionerà nei documenti nidificati nella query di aggiornamento,
Puoi provare un aggiornamento complesso con una query di aggregazione per gestire i tuoi casi se vuoi farlo in un'unica query,
Prendiamo un input di esempio e vediamo l'esempio per quanto riguarda i casi,
Caso 1: Se specificato messages.from
il campo esiste in messages
matrice
var to = "111";
var from = "222";
var subMessage = {
message: "test",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Caso 2: Se messages.from
il campo non esiste nell'array
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Caso 3: Se il documento non esiste
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
La tua domanda finale sarebbe,
- controlla solo da
to
condizione in questione - aggiorna parte, verifica la condizione,
- se
from
trovato inmessages
array quindi:$map
per iterare il ciclo dimessages
array e verifica la condizione sefrom
trovato quindi concatsubMessages
correnti array con nuovo inputsubMessage
usando$concatArrays
,$mergeObjects
per unire l'oggetto corrente con l'oggetto aggiornato
- altrimenti da non trovato, quindi concatena la nuova matrice di oggetti del messaggio nei
messages
correnti array usando$cocnatArrays
- se
upsert: true
, per inserire nuovo documento se non presente nella collezione
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 }
)