我将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 => Story_id => Story1 的部分中 S2
我现在找到的解决方案是找到元素 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.
不能使用 $ 来匹配多个级别的嵌套数组。这就是为什么在MongoDB中嵌套数组不是一个好主意,如果你预计搜索比顶级数组更深的属性。固定文档结构的替代方法是知道要更新除一个数组之外的所有数组中的哪些位置(或检索文档并找出索引,就像您正在做的那样)或检索文档,在客户端中更新它,然后重新插入它。
另一种选择是重新考虑如何在MongoDB中将数据建模为文档,这样就不会发生嵌套数组/在您的情况下,故事是元素集合的部分集合。您可以让故事由多个章节文档表示,而不是制作故事文档。该部分文档将共享一些通用字段值,以指示它们属于同一故事。然后,可以使用 $ 位置运算符将上述更新作为对一个部分文档的更新,以匹配和更新正确的元素。