包含嵌入文档

时间:2017-12-22 05:08:09

标签: mongodb nosql

假设我在阵列中获得了嵌入文档的以下文档:

{
    "name" : "test",
    "children" : [
        {
            "name" : "child1",
            "children" : [
                {
                    "name" : "sub1",
                    "children" : [
                        {"name" : "c1"},
                        {"name" : "c2"},
                        {"name" : "c3"},
                        {"name" : "c4"},
                        {"name" : "c5"}
                    ]
                }
            ]
        }, 
        {
            "name" : "child2",
            "children" : [
                {
                    "name" : "sub2",
                    "children" : [
                        {"name" : "c1"},
                        {"name" : "c2"},
                        {"name" : "c3"},
                        {"name" : "c4"}
                    ]
                }, 
                {
                    "name" : "sub3",
                    "children" : [
                        {"name" : "c1"},
                        {"name" : "c2"},
                        {"name" : "c3"},
                        {"name" : "c4"}
                    ]
                }, 
                {
                    "name" : "sub4",
                    "children" : [
                        {"name" : "c1"},
                        {"name" : "c2"},
                        {"name" : "c3"},
                        {"name" : "c4"}
                    ]
                }
            ]
        }
    ]
}

我们可以看到,test有两个孩子:child1child2,而孩子有自己的孩子,如sub1sub2,{ {1}},sub3等,等等。 目前,我必须更新一些儿童内容,但我遇到了以下两个问题:

第一个问题是关于sub4,当我意外地输入错字时(名称findOne()应为child1):

child2

我仍然可以正确地获取文档'test',但由于我输错了db.collection_name.findOne({ 'name': 'test', 'children.name': 'child1', // -> should be `child2` 'children.children.name': 'sub2' }) 实际上在sub2下,而不是child2,那么我怎么能得到正确的{{ {1}}结果?

第二个问题是关于child1,当我尝试更新findOne()的数组updateOne()时,它运行良好(代码也类似于官方文档中的示例):

child1

但是,当我还尝试更新children的数组(db.collection_name.updateOne({ 'name': 'test', 'children.name': 'child1' // locate child1 }, { '$set':{'children.$.children':[some other content]} }) 下)时,同样的方式失败,错误为sub3,这里的代码有问题:

child2

如果有人可以提前帮助解决这两个问题,我会非常感激,谢谢!

2 个答案:

答案 0 :(得分:1)

对于第一个问题,您可以使用$elemMatch查找确切的元素。

db.collection_name.findOne({
   'name':'test',
   children:{
      $elemMatch:{
         'name':'child2',
         'children.name':'sub2'
      }
   }
})

我猜mongo不支持多个嵌套数组更新,但如果您知道子阵列位置,则可以使用此方法。

db.collection_name.updateOne({
  'name':'test',
   children:{
      $elemMatch:{
         'name':'child2',
         'children.name':'sub3'
      }
   }
}
, {
    $set: {"children.$.children.1.children" : 
                    [
                        {"name" : "c1"},
                        {"name" : "c2"},
                        {"name" : "c3"},
                        {"name" : "c4"}
                    ]
         }
}
)

答案 1 :(得分:1)

第一个问题:查询数组时查询返回结果,因为匹配是针对数组的所有元素进行评估,即第一个匹配'children.name': 'child1'匹配第一个元素,第二个'children.children.name': 'sub2'匹配第二个元素。

使用$elemMatch(query)将两个条件匹配到同一个数组元素。

db.collection_name.findOne({
    'name': 'test',
    'children':{$elemMatch:{'name': 'child2', 'children.name': 'sub2'}}
})

比较上述方法1& 2

第二个问题:Mongodb 3.6现在通过arrayFilters表达式支持多个位置更新。

以下查询替换sub3子女的所有子女。

db.collection_name.updateOne(
 {'name': 'test'}, 
 {'$set':{'children.$[first].children.$[second].children':[some data]}},
 {'arrayFilters': [{ 'first.name': 'child2', 'second.name': 'sub3'}]}
)

以下查询在sub3孩子的子女中推送新孩子。

db.collection_name.updateOne(
 {'name': 'test'}, 
 {'$push':{'children.$[first].children.$[second].children':new child data}},
 {'arrayFilters': [{ 'first.name': 'child2', 'second.name': 'sub3'}]}
)