アップサートは、更新クエリのネストされたドキュメントでは機能しません
単一のクエリで実行する場合は、集計クエリを使用して複雑な更新を試して、ケースを処理できます。
入力例を取り上げて、ケースごとに例を見てみましょう。
ケース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にあります 次に配列:-
$mapmessagesのループを繰り返す 配列を作成し、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 }
)