【问题标题】:MongoDB updating fields in nested arrayMongoDB 更新嵌套数组中的字段
【发布时间】:2012-03-25 14:12:36
【问题描述】:

MongoDB 更新嵌套数组中的字段

如何在photos 数组中将“播放”设置为“播放照片”?

我只知道它的_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" 
}]

【问题讨论】:

    标签: php mongodb database


    【解决方案1】:

    此问题已解决。更新字段的功能 在嵌套的对象数组中,在 MongoDB 3.6+ 版本中可用。 查看位置运算符(全部和带有标识符)here

    //Update all docs in collection matching photo name "play" to "play photo"
    db.collectioname.update(
        {},
        { $set: { "albums.$[].photos.$[photo_field].name": "play photo" } },
        { arrayFilters: [  {"photo_field.name": "play"} ], multi: true}
    );
    
    //Update this specific doc given in question matching photo name "play" to "play photo"
    db.collectioname.update(
        {"_id" : ObjectId("4f41a5c7c32810e404000000")},
        { $set: { "albums.$[].photos.$[photo_field].name": "play photo" } },
        { arrayFilters: [  {"photo_field.name": "play"} ]}
    );
    

    这是为了帮助 MongoDB 3.6 之后来到这里的人

    【讨论】:

    • 您的示例中的photo_field 是什么意思?这是否意味着遍历照片中的所有字段,直到找到name
    • 是的,它会遍历相册和照片的每个索引并匹配“播放”,然后将其设置为“播放照片”。
    【解决方案2】:

    Tonilin 你不能直接更新这种类型的数组,你需要找到你想要更新的数组的索引,如果你想将name 更新为play photo,那么你必须找到的索引photos 其中名称为 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);
    }
    

    【讨论】:

      【解决方案3】:

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

      这是一个已知问题,计划在此处进行开发:https://jira.mongodb.org/browse/SERVER-831

      恐怕在那之前你必须稍微标准化你的架构。

      【讨论】:

      • 谢谢,但我可能不会更改我的架构。我将拉出元素,修改并推回。尽管效率低下。
      • 这是一个选项,但存在严重的并发问题(一次写入可能会覆盖并发写入的结果),因此请谨慎使用。
      猜你喜欢
      • 1970-01-01
      • 2013-11-05
      • 2020-05-08
      • 2011-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多