この特定の埋め込みサブドキュメントを持つすべてのドキュメントの配列内のサブドキュメントを更新 (置換) したいと考えています。
私のサンプルコンテンツオブジェクトは次のとおりです。
{
"_id" : ObjectId("51f289e5345f9d10090022ef"),
"title" : "This is a content",
"descriptors" : [
{
"_id" : ObjectId("51f289e5345f9d10090022f4"),
"name" : "This is a descriptor",
"type" : "This is a property"
},
{
"_id" : ObjectId("51f289e5345f9d10090022f0"),
"name" : "This is another descriptor",
"type" : "This is another property"
}
]
}
特定のdescriptor._id
. あるサブドキュメントを別のサブドキュメントに置き換えたいです (それぞれ古いオブジェクトの更新バージョンに置き換えますが、必ずしも同じプロパティとは限りません)。
これはRoboMongo / shellでうまく機能しますが...
db.Content.update(
{
'descriptors._id': ObjectId("51f289e5345f9d10090022f4")
},
{
$set: {
'descriptors.$': {
"_id" : ObjectId("51f289e5345f9d10090022f4"),
"name" : "This is the updated descriptor",
"category" : "This is a new property"
}
}
},
{
'multi': true
})
...そしてプレーンなphpメソッドで...
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$mongo = new \Mongo('mongodb://localhost:27017');
$database = $mongo->selectDB('MyDatabase');
$output = $database->selectCollection('Content')->update(
array('descriptors._id' => $descriptor['_id']),
array('$set' => array('descriptors.$' => $descriptor)),
array("multiple" => true)
);
... Doctrine MongoDB ODMでは動作しません...
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$query = $dm->createQueryBuilder('Content')
->update()->multiple(true)
->field('descriptors._id')->equals($descriptor['_id'])
->field('descriptors.$')->set($descriptor)
->getQuery()->execute();
...次のエラーで失敗するため:
注意: 未定義のオフセット: C:\MyProject\vendor\doctrine\mongodb-odm\lib\Doctrine\ODM\MongoDB\Persisters\DocumentPersister.php 行 998 の 2
したがって、Doctrine MongoDB ODMにはドット表記の 3 つの部分が必要だと思います。サブドキュメントのプロパティを反復処理して手動で設定するのは、あまり良くない解決策です。
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$query = $dm->createQueryBuilder('Content')
->update()->multiple(true)
->field('descriptors._id')->equals($descriptor['_id']);
foreach ($descriptor as $key => $value) {
$query->field('descriptors.$.'.$key)->set($value);
}
$query->getQuery()->execute();
ただし、これは既存のプロパティを更新して新しいプロパティを追加するだけで、古い/不要なプロパティをサブドキュメントから削除しません。
問題を解決する方法についてのアイデア:
- 簡単なクエリで
- Doctrine MongoDB ODM の使用中
- PHPでサブドキュメント配列をループせずに
私は使用しています:
- モンゴ サーバー: 2.4.5
- PHP: 5.4.16
- PHP モンゴ ドライバー: 1.4.1
作曲:
"php": ">=5.3.3",
"symfony/symfony": "2.3.*",
"doctrine/orm": ">=2.2.3,<2.4-dev",
"doctrine/doctrine-bundle": "1.2.*",
"doctrine/mongodb-odm": "1.0.*@dev",
"doctrine/mongodb-odm-bundle": "3.0.*@dev"