0

サブ配列のサブドキュメントを更新しようとしていますが、配列内の要素の位置が常に同じであるとは期待できません。更新するにはどうすればよいですか。

たとえば、これが私のドキュメントです。別のタグ オブジェクト (key/val) を次のtags配列にプッシュしたいだけですreal_pagenum: 1 の pdf_idObjectId("50634e26dc7c22c64d00000a")

{
    "_id" : ObjectId("503b83dfad79cc8d26000004"),
    "pdfs" : [
        {
            "_id" : ObjectId("50634e26dc7c22c64d00000a"),
            "pages" : [
                {
                    "real_pagenum" : 1,
                    "_id" : ObjectId("50634e74dc7c22c64d00002b"),
                    "tags" : [
                        {
                            "key" : "Item",
                            "val" : "foo"
                        },
                        {
                            "key" : "Item",
                            "val" : "bar"
                        }

                    ]

                },
                {
                    "real_pagenum" : 2,
                    "_id" : ObjectId("50634e74dc7c22c64d00002b")
                }
            ],
            "title" : "PDF3",
            "version" : 3
        }
    ],
}

繰り返しますが、目標は、最初に で正しい pdf をターゲットにし_id、次に で正しいページをターゲットにして、その pdf のページの配列real_pagenumにプッシュすることです。tags

私が試した:

db.projects.update({'pdfs.pdf_id':ObjectId("50634e25dc7c22c64d000007")},
    {$push:{'pages.$.tags':{'key':'foo','val':'bar'}}},false,false);

しかし、それは私が必要とするレベルには達しません。位置演算子と実際の要素 positionの組み合わせを使用できることを読みましたが、要素の位置を保証または知ることはできません。

4

3 に答える 3

1

現在、これは不可能です。ドキュメントツリーの最上位の配列は、位置演算子を使用してのみアドレス指定できます。より深い配列にアクセスできるのは、要素の正確な位置がわかっている場合のみです。

これは現在未解決の問題です:https ://jira.mongodb.org/browse/SERVER-831

于 2012-09-27T15:14:46.963 に答える
0

ネストされた配列に位置演算子を使用できないことは、mongodbで現在報告されているバグです。

https://jira.mongodb.org/browse/SERVER-831

位置演算子は、当面の間、1つのクエリで複数回使用することもできません。

あなたの場合にこれを処理する最良の方法は、スキーマを変更することかもしれません。一般に、BSONドキュメントの最大サイズは16 MBであるため、ドキュメント内に任意のサイズに拡大する配列を含めることはお勧めできません。

特にこの場合、ドキュメントは基本的にPDFの配列にすぎないように思われるためです。PDF用に別のコレクションを作成することを検討しましたか?

于 2012-09-27T15:15:41.863 に答える
0

ドキュメントのアトミック更新を行う限り、他の答えは正しいです。

これは最適なスキーマではないように見えることに非常に同意します.pdfごとのドキュメントは、位置演算子でアトミックに更新できる各ドキュメント内のページの配列のみを持っている場合、より理にかなっているかもしれません.

スキーマを変更できない場合でも、必要な更新を行うことができますが、スレッド セーフではない可能性があります。ドキュメント全体をアプリケーションに読み込み、コード内の適切なフィールドを変更して、アイテムを保存できます。複数のスレッドが互いに踏みつけないようにしたい場合は、各ドキュメントにバージョンを保持し、「更新」ごとにそれをインクリメントする必要があります。これは、その間にバージョンが変更されていないことを条件とします. より複雑で、現在のスキーマに追加のフィールドが必要ですが、少なくとも、必要なことを行うことができます。

于 2012-09-27T15:45:17.693 に答える