2012-03-08 103 views
3
在嵌套数组

MongoDB的嵌套阵列更新领域

我如何可以设置照片阵列中的“玩”到“播放照片”

MongoDB的更新领域?

我只知道它的_id。

"_id": ObjectId("4f41a5c7c32810e404000000"), 
"albums": [ 
{ 
    "_id": ObjectId("4f545d1bc328103812000000"), 
    "name": "album1" , 
    "photos":[{ 
     "_id": ObjectId("4f545d1bc328103812d00000"), 
     "name":"travel photo" 
    },{ 
     "_id": ObjectId("4f545d1bc328103812c00000"), 
     "name":"play" 
    }] 
}, 
{ 
    "_id": ObjectId("4f545f56c328103c12000000"), 
    "name": "album2" 
}, 
{ 
    "_id": ObjectId("4f545f68c328103012000000"), 
    "name": "album3" 
}, 
{ 
    "_id": ObjectId("4f546642c328103c12000001"), 
    "name": "album4" 
}] 

回答

6

你不能。位置运算符仅适用于文档层次结构中的第一个数组。因此,您不能操纵更深层次的阵列中的单个元素。

这是一个已知的问题,并计划开发这里:https://jira.mongodb.org/browse/SERVER-831

直到那个时候你就必须正常化您的模式有点我害怕。

+0

谢谢, 但我可能不会改变我的架构。 我将拉动元素,修改并推回。 虽然它效率低下。 – tonilin 2012-03-08 09:13:45

+3

这是一个选项,但存在严重的并发问题(一次写入可能会覆盖并发写入的结果),请小心使用。 – 2012-03-08 09:25:32

0

Tonilin你不能直接更新为此,你需要在其中找到你想要nameplay photo,那么你必须要找到的photos其中name索引更新,如果你想更新一样,数组的索引这种类型的数组是play。 为此,我用这个代码,如:

$m = new Mongo(); 
$db=$m->yourdatabase; 
//testarray is my collection name 
$result=$db->testarray->find(); 
$index=''; 
foreach($result as $res) 
{ 
    if(array_key_exists("albums",$res)) 
    { 
     foreach($res['albums'] as $ralbum) 
     { 
      if(array_key_exists("photos",$ralbum)) 
      { 
       foreach($ralbum['photos'] as $k=>$rphotos) 
       { 
        if(array_key_exists("name",$rphotos)) 
         if($rphotos['name']=='play') 
          $index=$k; 
       } 
      } 
     } 
    } 
} 
//echo $index; 

//现在更新数据库将该值使用此代码...

if($index!=='') 
{ 
    //Run like this in Shell 
    //db.testarray.update({"albums.photos._id":ObjectId("4f545d1bc328103812d00000")},{'$set':{"albums.$.photos.1.name":"play132"}}) 
    $condition=array("albums.photos._id"=>new MongoId("4f545d1bc328103812d00000")); 
    $data=array('$set'=>array("albums.$.photos.".$index.".name"=>"play photo")); 
    $result=$db->testarray->update($condition,$data); 
    $status=$db->Command(array('getlasterror'=>1)); 
    print_r($status); 
}