MongoDB查询settings动态键下enabled为yes的条目报错如何解决
问题原因
$search是MongoDB Atlas专属的搜索功能,非Atlas托管的自建MongoDB实例不支持该聚合阶段,因此会触发未识别阶段的报错。- 常规MongoDB查询的字段路径不支持直接用
*通配符匹配嵌套对象的动态键,因此$match阶段的settings.*.enabled写法无法匹配到对应数据,没有返回结果。
可行解决方案
核心思路是通过聚合管道的$objectToArray操作符,将settings字段的动态键对象转换为可遍历的键值对数组,再过滤符合条件的项。
方案1:返回文档+所有符合条件的配置项
如果需要在结果中返回所有enabled为yes的配置项明细,可使用以下写法:
return Customer::raw(function($collection) { return $collection->aggregate([ // 预过滤:只处理存在settings字段的文档,减少计算量 [ '$match' => [ 'settings' => ['$exists' => true] ] ], // 将settings动态对象转为键值对数组,结构为 [{"k":"foo","v":{"type":"custom","enabled":"yes"}}] [ '$addFields' => [ 'settings_arr' => ['$objectToArray' => '$settings'] ] ], // 过滤出enabled为yes的配置项 [ '$addFields' => [ 'enabled_settings' => [ '$filter' => [ 'input' => '$settings_arr', 'cond' => ['$eq' => ['$$this.v.enabled', 'yes']] ] ] ] ], // 移除中间临时字段,不需要可删除该阶段 [ '$project' => [ 'settings_arr' => 0 ] ] ]); });
返回结果中enabled_settings字段就是所有符合要求的配置项,如果需要转回对象格式,可额外添加$arrayToObject操作符处理enabled_settings字段。
方案2:仅筛选符合条件的文档
如果只需要筛选出「至少存在一个enabled为yes的配置项」的文档,不需要返回配置明细,可使用简化写法:
return Customer::raw(function($collection) { return $collection->aggregate([ [ '$match' => [ '$expr' => [ // 判断符合条件的配置项数量是否大于0 '$gt' => [ [ '$size' => [ '$filter' => [ 'input' => ['$objectToArray' => '$settings'], 'cond' => ['$eq' => ['$$this.v.enabled', 'yes']] ] ] ], 0 ] ] ] ] ]); });
内容的提问来源于stack exchange,提问作者Rehan
相关产品推荐
相关产品推荐

