我有一个如下所示的数据库结构:
{
"_id" : 1,
"comments" : [
{
"_id" : 2,
"content" : "xxx"
}
]
}
我在评论中更新了一个新的子文档。没关系。
db.test.update(
{"_id" : 1, "comments._id" : 2},
{$push : {"comments.$.comments" : {_id : 3, content:"xxx"}}}
)
之后的DB结构:
{
"_id" : 1,
"comments" : [
{
"_id" : 2,
"comments" : [
{
"id" : 3,
"content" : "xxx"
}
],
"content" : "xxx"
}
]
}
但是当我在注释字段中更新_id为3的新子文档时,出现错误:
db.test.update(
{"_id" : 1, "comments.comments.id" : 3},
{$push : {"comments.comments.$.comments" : {id : 4, content:"xxx"}}}
)
错误消息:
无法使用字符串字段名称附加到数组:comments
答案 0 :(得分:3)
嗯,如果你考虑一下,这是完全有道理的。 MongoDb具有神奇地解决某些事物的优点和缺点。 当您在数据库中查询特定的常规字段时,如下所示:
{ field : "value" }
查询{field:“value”}完全有意义,如果值是数组的一部分但是Mongo为你解决它,那么结果是:
{ field : ["value", "anothervalue"] }
Mongo遍历所有这些并将“value”匹配到字段中,您不必考虑它。它完美地工作......只有一个层次,因为如果你有多个级别就无法猜出你想做什么
在您的情况下,第一个查询有效,因为在此示例中就是这种情况:
db.test.update(
{"_id" : 1, "comments._id" : 2},
{$push : {"comments.$.comments" : {_id : 3, content:"xxx"}}}
)
在第一级匹配_id,在第二级匹配comments._id,结果得到一个数组,但Mongo能够解决它。
但在第二种情况下,想想你需要什么,让我们隔离where子句:
{"_id" : 1, "comments.comments.id" : 3},
“使用_id:1从主要收藏记录中提供给我”(一份文档) “并且注释里面的注释和id = 3”(数组*数组)
第一级很容易解决,comments.id,第二级是不可能的,因为注释返回一个数组,但是另一个级别是一个数组数组,而Mongo得到一个数组数组,因此无法推送一个文档到数组的所有记录。
解决方案是缩小你的where子句以获得评论中的唯一文档(可能是第一个),但这不是一个好的解决方案,因为你永远不知道你正在寻找的文档的位置是什么,使用shell我认为唯一可行的选择是分两步完成。检查这个有效的查询(不管解决方案),但“解决”多个数组部分将其固定到第一条记录:
db.test.update(
{"_id" : 1, "comments.0.comments._id" : 3},
{$push : {"comments.0.comments.$.comments" : {id : 4, content:"xxx"}}}
)