我将MongoDB与PHP驱动程序一起使用,为方便起见,我将用这种语法编写查询, 我想找到一个更优雅的解决方案,我今天发现了以下问题。
我有这个集合“故事”与嵌套文档:
收集故事:
{
"_id":"Story1",
"title":null,
"slug":null,
"sections":[
{
"id_section":"S1",
"index":0,
"type":"0",
"elements":[
{
"id_element":"001",
"text":"img",
"layout":1
}
]
},
{
"id_section":"S2",
"index":0,
"type":"0",
"elements":[
{
"id_element":"001",
"text":"hello world",
"layout":1
},
{
"id_element":"002",
"text":"default text",
"layout":1
},
{
"id_element":"003",
"text":"hello world 3",
"layout":"2"
}
]
}
]
}
假设您要使用id_element =>更改元素的值002出现在id_section =>部分带有_id =>的故事的S2 Story1
我现在发现的解决方案是找到元素002的“位置”并执行以下操作
1]
$r=$m->db->plot->findOne(array("_id" => 'Story1',
"sections.id_section"=>'S2'),
array('_id'=>false,'sections.$.elements'=>true));
2]
foreach($r['sections'][0]['elements'] as $key=>$value){
if($value['id_element']=='002'){
$position=$key;
break;
}
3]
$m->db->story->update(array('_id'=>'Story1','sections.id_section'=>'S2','sections.elements.id_element'=>'002'),
array('$set'=>array('sections.$.elements.'.$position.'.text'=>'NEW TEXT')),
array('w'=>1));
我再说一遍,我认为这不是一个优雅的解决方案,我注意到这是一个常见的问题。
感谢您的帮助 S上。
答案 0 :(得分:1)
您不能使用$来匹配多级嵌套数组。这就是为什么如果你期望在比顶级数组更深的地方搜索属性,那么在MongoDB中嵌套数组并不是一个好主意。固定文档结构的替代方法是知道除了一个要更新的数组中的哪个位置(或者检索文档并找到索引,正如您所做)或检索文档,更新它客户端,然后重新插入。
另一种选择是重新考虑如何将数据建模为MongoDB中的文档,以便嵌套数组不会发生/在您的情况下,故事是一系列元素集合的部分。您可以通过多个部分文档来表示故事,而不是制作故事文档。部分文档将共享一些共同的字段值,以表明它们属于同一个故事。然后,上述更新可以作为一个部分文档的更新,使用$ position运算符来匹配和更新正确的元素。