Upsert ne fonctionnera pas dans les documents imbriqués dans la requête de mise à jour,
Vous pouvez essayer une mise à jour complexe avec une requête d'agrégation pour gérer vos cas si vous souhaitez le faire en une seule requête,
Prenons un exemple d'entrée et voyons l'exemple au cas par cas,
Cas 1 : Si spécifié messages.from
le champ existe dans messages
tableau
var to = "111";
var from = "222";
var subMessage = {
message: "test",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Cas 2 : Si messages.from
le champ n'existe pas dans le tableau
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Cas 3 : Si le document n'existe pas
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Votre dernière requête serait :
- cochez uniquement
to
condition dans la requête - mettre à jour la pièce, vérifier l'état,
- si
from
trouvé dans lesmessages
tableau alors :$map
pour itérer la boucle demessages
tableau et vérifier la condition sifrom
trouvé puis concat lessubMessages
actuels tableau avec une nouvelle entréesubMessage
en utilisant$concatArrays
,$mergeObjects
pour fusionner l'objet courant avec l'objet mis à jour
- else from not found then concat new message object array in current
messages
tableau utilisant$cocnatArrays
- si
upsert: true
, pour insérer un nouveau document s'il n'est pas trouvé dans la collection
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 }
)