アップサートは、更新クエリのネストされたドキュメントでは機能しません
単一のクエリで実行する場合は、集計クエリを使用して複雑な更新を試して、ケースを処理できます。
入力例を取り上げて、ケースごとに例を見てみましょう。
ケース1: 指定されている場合messages.from
messages
にフィールドが存在します 配列
var to = "111";
var from = "222";
var subMessage = {
message: "test",
date: ISODate("2021-06-29T15:57:53.975Z")
};
ケース2: messages.from
の場合 フィールドが配列に存在しません
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
ケース3: ドキュメントが存在しない場合
var to = "111";
var from = "333";
var subMessage = {
message: "test2",
date: ISODate("2021-06-29T15:57:53.975Z")
};
最終的なクエリは、
-
to
のみをチェック クエリの条件 - パーツを更新し、状態を確認します。
-
from
の場合messages
にあります 次に配列:-
$map
messages
のループを繰り返す 配列を作成し、from
の場合は条件を確認します 見つかった後、現在のsubMessages
を連結します 新しい入力を持つ配列subMessage
$concatArrays
を使用する 、$mergeObjects
現在のオブジェクトを更新されたオブジェクトとマージするには
-
- それ以外の場合は見つかりませんでした。次に、現在の
messages
に新しいメッセージオブジェクト配列を連結します。$cocnatArrays
を使用した配列
-
-
upsert: true
、コレクションに見つからない場合に新しいドキュメントを挿入する
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 }
)