6

この質問が以前に尋ねられたことは知っていますが、それは別のシナリオです。次のようなコレクションが欲しいです。

{
    "_id" : ObjectId("4c28f62cbf8544c60506f11d"),
    "pk": 1,
    "forums": [{
        "pk": 1,
        "thread_count": 10, 
        "post_count": 20,
    }, {
        "pk": 2,
        "thread_count": 5, 
        "post_count": 24,
    }]
}

私がやりたいのは、「フォーラム」アイテムをアップサートし、カウンターをインクリメントするか、アイテムが存在しない場合は追加することです。

たとえば、次のようなことを行います (意味があることを願っています)。

db.mycollection.update({
    "pk": 3,
    "forums.pk": 2
}, {
    "$inc": {"forums.$.thread_count": 1},
    "$inc": {"forums.$.post_count": 1},
}, true)

そして持っています:

{
    "_id" : ObjectId("4c28f62cbf8544c60506f11d"),
    "pk": 1,
    "forums": [{
        "pk": 1,
        "thread_count": 10, 
        "post_count": 20,
    }, {
        "pk": 2,
        "thread_count": 5, 
        "post_count": 24,
    }]
},
{
    "_id" : ObjectId("4c28f62cbf8544c60506f11e"),
    "pk": 3,
    "forums": [{
        "pk": 2,
        "thread_count": 1, 
        "post_count": 1,
    }]
}

私は確かに3つのステップでそれを作ることができます:

  1. コレクション全体を新しいアイテムでアップサートする
  2. addToフォーラム項目をリストに設定する
  3. 位置演算子を使用してフォーラム アイテム カウンターをインクリメントする

つまり、次のようになります。

db.mycollection.update({pk:3}, {pk:3}, true)
db.mycollection.update({pk:3}, {$addToSet: {forums: {pk:2}}})
db.mycollection.update({pk:3, 'forums.pk': 2}, {$inc: {'forums.$.thread_counter': 1, {'forums.$.post_counter': 1}})

それを行うより効率的な方法を知っていますか?TIA、ジェルマーノ

4

1 に答える 1

10

お気づきかもしれませんが、位置演算子は upsert では使用できません。

upsert位置演算子は、一致する配列要素が必要なため、と組み合わせることはできません。更新の結果が挿入された場合、「$」は文字どおりフィールド名として使用されます。

したがって、単一のクエリで目的の結果を達成することはできません。

ドキュメントの作成とカウンターの更新を分離する必要があります。あなた自身の解決策は正しい方向に進んでいます。次の 2 つのクエリに要約できます。

// optionally create the document, including the array
db.mycollection.update({pk:3}, {$addToSet: {forums: {pk:2}}}, true)

// update the counters in the array item
db.mycollection.update({pk:3, 'forums.pk': 2}, {$inc: {'forums.$.thread_counter': 1, 'forums.$.post_counter': 1}})
于 2010-11-03T11:03:26.437 に答える