0

我正在尝试更新子数组的子文档,但我不能指望元素在数组中的位置始终相同,那么我该如何更新它。

例如,这是我的文档,我只想将另一个标签对象(key/val)推送到pdf的tags数组:1和real_pagenum_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 by _id,然后是正确的 page byreal_pagenum并推入该 pdf 的页面tags数组。

我试过:

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

但这并没有达到我需要的水平。我读过我可以使用位置运算符与实际元素位置的组合,但同样,我不能保证或知道元素的位置。

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

位置运算符也不能在一个查询中多次使用,暂时。

在您的情况下处理此问题的最佳方法可能是更改您的架构。一般来说,在文档中包含会增长到任意大小的数组并不是一个好主意,因为 BSON 文档的最大大小为 16mb。

特别是因为在这种情况下,您的文档似乎基本上只是一个 pdf 数组。您是否考虑过为 pdf 创建单独的集合?

于 2012-09-27T15:15:41.863 回答
0

就对文档进行原子更新而言,其他答案是正确的。

我非常同意这看起来不是最佳模式 - 每个 pdf 的文档可能更有意义,然后您在每个文档中只有一个页面数组,您可以使用位置运算符进行原子更新。

如果您无法修改架构,您仍然可以进行所需的更新,但它可能不是线程安全的。您可以将整个文档读入您的应用程序,修改代码中的相应字段,然后保存该项目。如果您想确保多个线程不会相互踩踏,您必须在每个文档中保留一个版本并在每次“更新”时增加它,这取决于版本没有同时更改. 它更复杂,它仍然需要当前模式中的附加字段,但至少它允许您执行您声明需要执行的操作。

于 2012-09-27T15:45:17.693 回答