简体   繁体   English

在MongoDB PHP中更新嵌套文档中的字段

[英]Updating field in nested documents in mongodb php

I use MongoDB with PHP driver, so for convenience I will write the query with this syntax, I would like to find a more elegant solution that I found today for the following problem. 我将MongoDB与PHP驱动程序一起使用,因此为了方便起见,我将使用此语法编写查询,我想找到一个今天针对以下问题找到的更优雅的解决方案。

I have this collection "Story" with nested document: 我有这个带有嵌套文档的“故事”集合:

Collection Story: 收藏故事:

{  
   "_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"
            }
         ]
      }
   ]
}

Assuming you want to change the value of the element with id_element => 002 present in section with id_section => S2 of Story with _id => Story1 假设您要更改id_element => 002的元素的值,该元素存在于id_section => Story的S2和_id => Story1的section中

The solution I've found now is to find the "position" of element 002 and do the following 我现在找到的解决方案是找到元素002的“位置”并执行以下操作

1] 1]

$r=$m->db->plot->findOne(array("_id" => 'Story1',
                                        "sections.id_section"=>'S2'),
                                        array('_id'=>false,'sections.$.elements'=>true));

2] 2]

foreach($r['sections'][0]['elements'] as $key=>$value){
    if($value['id_element']=='002'){
        $position=$key;
        break;
    }

3] 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));

I repeat that I do not think an elegant solution, and I noticed that it is a common problem. 我再说一遍,我认为这不是一个很好的解决方案,并且我注意到这是一个普遍的问题。

Thank you for your help S. 谢谢您的帮助。

You can't use $ to match multiple levels of nested arrays. 您不能使用$来匹配多层嵌套数组。 This is why it's not a good idea to nest arrays in MongoDB if you anticipate searching on properties anywhere deeper than the top level array. 这就是为什么如果您希望在比顶级数组更深的地方搜索属性,那么在MongoDB中嵌套数组不是一个好主意的原因。 The alternatives for a fixed document structure are to know which positions in all but one of the arrays you want to update at (or to retrieve the document and find out the indexes, as you are doing) or to retrieve the document, update it in the client, and reinsert it. 固定文档结构的替代方法是知道要更新的数组(除其中一个数组之外)中所有数组的哪个位置(或在执行操作时检索文档并找出索引)或检索文档并在其中更新客户,然后重新插入。

The other option is to rethink how the data is modeled as documents in MongoDB so that nested arrays don't happen/ In your case, a story is a collection of sections which are collections of elements. 另一个选择是重新考虑如何在MongoDB中将数据建模为文档,以免发生嵌套数组。在您的情况下,故事是部分的集合,这些部分是元素的集合。 Instead of making a story document, you could have a story be represented by multiple section documents. 代替制作故事文档,您可以使故事由多个部分文档表示。 The section documents would share some common field value to indicate they belong to the same story. 章节文档将共享一些公共字段值,以指示它们属于同一故事。 The above update would then be possible as an update on one section document using the $ positional operator to match and update the correct element. 然后,可以使用$位置运算符来匹配和更新正确的元素,从而对一个截面文档进行上述更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM