MongoDB обновляет поля во вложенном массиве - PullRequest
4 голосов
/ 08 марта 2012

Обновление полей 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" 
}]

Ответы [ 3 ]

7 голосов
/ 08 марта 2012

Вы не можете. Позиционный оператор доступен только для первого массива в вашей иерархии документов. Таким образом, вы не можете манипулировать отдельными элементами более глубоких массивов Нестер.

Это известная проблема, разработка которой запланирована здесь: https://jira.mongodb.org/browse/SERVER-831

Боюсь, до этого времени вам придется немного нормализовать свою схему.

6 голосов
/ 30 июля 2018

Эта проблема была решена.Возможность обновления полей внутри вложенного массива объектов, доступна в версиях MongoDB 3.6+.Смотрите позиционные операторы (все и с идентификатором) здесь .

//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

0 голосов
/ 02 мая 2012

Tonilin You Cant Обновите этот тип массива напрямую, для этого вам нужно найти индекс этого массива, в котором вы хотите обновить, например, если вы хотите обновить 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...