PHP操作MongoDB时子文档数组更新及按索引批量更新子文档问题
问题分析
你的代码无法正常执行有两个核心原因:
- 你提供的示例数据本身存在语法错误,
"id":7,}多了一个多余的逗号,实际存储时需要先修正该问题。 - 当前数据结构中
messages是嵌套对象,而非索引数组:你提供的示例数据里messages的结构是{"1": {"type":"1", ...}},属于键值对对象,MongoDB的数组操作符(比如$[m]数组过滤器)仅支持对真正的数组类型字段生效,对嵌套对象不生效。
解决方案
方案1:保留现有嵌套对象结构,更新指定索引的子文档
如果不调整数据结构,要更新索引为1、2、3的子文档,直接指定完整的嵌套键路径即可,示例如下:
// 更新索引为1的整个messages子文档 $result = $collection->updateOne( ['_id' => new MongoDB\BSON\ObjectID('6163f2c9fc197a54f03ca8c8')], [ '$set' => [ 'messages.1' => [ 'type' => 'new type', 'time' => date('d.m.Y H:i:s'), 'message' => '更新后的内容' ] ] ] ); // 批量更新索引1、2、3的子文档同理,直接在$set里加对应键即可 $result = $collection->updateOne( ['_id' => new MongoDB\BSON\ObjectID('6163f2c9fc197a54f03ca8c8')], [ '$set' => [ 'messages.1' => ['type' => '1', 'time' => 'xxx', 'message' => '更新1'], 'messages.2' => ['type' => '2', 'time' => 'xxx', 'message' => '更新2'], 'messages.3' => ['type' => '3', 'time' => 'xxx', 'message' => '更新3'], ] ] );
方案2:调整为数组结构(推荐)
如果你的messages本身是按顺序存储的序列数据,建议调整为数组结构,更适配MongoDB的操作语法,调整后的数据结构示例:
{ "_id": {"$oid":"6163f2c9fc197a54f03ca8c8"}, "id":7, "messages": [ {"type":"1","time":"19.04.2020 09:14:42","message":"This is testmsg"}, {"type":"2","time":"xxx","message":"msg2"} ], "ssg":"ruther" }
调整后可实现你的两个需求:
- 批量更新所有type为test的子文档的direction字段
$result = $collection->updateMany( [ '_id' => new MongoDB\BSON\ObjectID('61613dcd437b996bc227ffe2'), 'messages.type' => 'test' ], ['$set' => ['messages.$[m].direction' => '999']], [ 'arrayFilters' => [['m.type'=> 'test']] ] );
注:multi参数在updateMany方法中不需要额外指定,updateMany本身就会匹配所有符合条件的文档。
- 更新索引为1、2、3的整个子文档
// 更新索引1、2、3的整个子文档,数组索引从0开始计数 $result = $collection->updateOne( ['_id' => new MongoDB\BSON\ObjectID('6163f2c9fc197a54f03ca8c8')], [ '$set' => [ 'messages.1' => ['type' => 'new1', 'time' => 'xxx', 'message' => '新内容1'], 'messages.2' => ['type' => 'new2', 'time' => 'xxx', 'message' => '新内容2'], 'messages.3' => ['type' => 'new3', 'time' => 'xxx', 'message' => '新内容3'], ] ] );
内容的提问来源于stack exchange,提问作者Shail
相关产品推荐
相关产品推荐

