我正在尝试更新子数组的子文档,但我不能指望数组中元素的位置始终相同,所以如何更新它。
例如,这是我的文档,我只是想将另一个标记对象(key / val)推送到tags
的{{1}}数组{1}}:pdf的real_pagenum
_id
ObjectId("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
但这没有达到我需要的水平。我读过我可以使用combination of the positional operator with actual element position,但我再也不能保证或知道该元素的位置。
答案 0 :(得分:1)
目前无法做到这一点。您只能使用位置运算符来处理文档树中的最高级别数组。只有知道确切的元素位置,才能访问任何更深的数组。
目前这是一个未解决的问题:https://jira.mongodb.org/browse/SERVER-831
答案 1 :(得分:0)
mongodb中当前提交的错误是位置运算符不能用于嵌套数组:
https://jira.mongodb.org/browse/SERVER-831
目前,位置运算符也不能在一个查询中多次使用。
在您的情况下处理此问题的最佳方法可能是更改您的架构。通常,将文档中的数组增长到任意大小并不是一个好主意,因为BSON文档的最大大小为16mb。
特别是因为在这种情况下,您的文档似乎基本上只是一个pdf数组。您是否考虑过为pdfs创建单独的集合?
答案 2 :(得分:0)
就文档的原子更新而言,其他答案是正确的。
我非常同意这看起来不是最优的架构 - 每个pdf文档可能更有意义,因此每个文档中只有一个页面数组,您可以使用位置操作符进行原子更新。
如果您无法修改架构,您仍然可以进行所需的更新,但它可能不是线程安全的。您可以将整个文档读入您的应用程序,修改代码中的相应字段,然后保存该项目。如果你想确保多个线程不会互相攻击,你必须在每个文档中保留一个版本并在每个“更新”上增加它,这将取决于同时没有更改的版本。它更复杂,它仍然需要当前架构中的一个额外字段,但至少它允许你做你所说的你需要做的事情。