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
tocondition dans la requête - mettre à jour la pièce, vérifier l'état,
- si
fromtrouvé dans lesmessagestableau alors :$mappour itérer la boucle demessagestableau et vérifier la condition sifromtrouvé puis concat lessubMessagesactuels tableau avec une nouvelle entréesubMessageen utilisant$concatArrays,$mergeObjectspour fusionner l'objet courant avec l'objet mis à jour
- else from not found then concat new message object array in current
messagestableau 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 }
)