Upsert nie będzie działać w zagnieżdżonych dokumentach w zapytaniu aktualizacyjnym,
Możesz wypróbować złożoną aktualizację za pomocą zapytania agregującego, aby obsłużyć swoje sprawy, jeśli chcesz to zrobić w jednym zapytaniu,
Weźmy przykładowe dane wejściowe i zobaczmy przykładowe przypadki,
Przypadek 1: Jeśli określono messages.from
pole istnieje w messages
tablica
var to = "111";
var from = "222";
var subMessage = {
message: "test",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Przypadek 2: Jeśli messages.from
pole nie istnieje w tablicy
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Przypadek 3: Jeśli dokument nie istnieje
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
Twoje ostatnie pytanie brzmiałoby:
- sprawdzaj tylko
to
warunek w zapytaniu - zaktualizuj część, sprawdź stan,
- jeśli
from
znalezione wmessages
tablica to:$map
do iteracji pętlimessages
tablica i sprawdź warunek, jeślifrom
znaleziono, a następnie połącz bieżącesubMessages
tablica z nowym wejściemsubMessage
za pomocą$concatArrays
,$mergeObjects
scalić bieżący obiekt ze zaktualizowanym obiektem
- inne z nie znaleziono, a następnie połącz nową tablicę obiektów wiadomości w bieżących
messages
tablica za pomocą$cocnatArrays
- jeśli
upsert: true
, aby wstawić nowy dokument, jeśli nie został znaleziony w kolekcji
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 }
)