You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP操作MongoDB如何实现仅匹配子文档键名的查询

PHP操作MongoDB匹配子文档键名查询方案

需求说明

需要实现等价于MySQL users like '"14:"' or invoice_id ="2"的查询效果,MongoDB中存储的文档结构如下:

{
  "invoice_id": 0,
  "users": {
    "14": "2022-06-09 10:56:10",
    "212": "2022-06-09 04:05:35"
  }
},
{
  "invoice_id": 2,
  "users": {
    "15": "2022-06-09 10:56:10",
    "246": "2022-06-09 04:05:35"
  }
}

核心查询目标:筛选出users子文档中存在键名为14,或者invoice_id值为2的记录。
原有错误写法问题:

$data["users.0"] = new MongoDB\BSON\Regex("14");
$result = $collection->find($data, $option);

该写法仅会匹配子文档的字段值,无法针对子文档的键名做匹配,无法达到预期效果。


正确实现代码

根据查询场景分两种实现方式:

  • 固定键名精确匹配(推荐)
    如果是明确判断子文档是否存在指定键名(比如本需求中固定判断键14是否存在),直接使用$exists操作符即可,性能最优,可命中索引:

    $filter = [
        '$or' => [
            // 判断users子文档下键"14"是否存在
            ['users.14' => ['$exists' => true]],
            // 匹配invoice_id=2的记录
            ['invoice_id' => 2]
        ]
    ];
    $result = $collection->find($filter, $option);
    
  • 模糊匹配子文档键名
    如果需要用正则模糊匹配子文档的键名(比如匹配所有键名包含14的记录,而非固定精确键名),需要先用$objectToArray将子文档转为{k:键名, v:键值}格式的数组,再对数组元素的k字段(即原键名)做正则匹配:

    $filter = [
        '$or' => [
            [
                '$expr' => [
                    '$gt' => [
                        [
                            '$size' => [
                                '$filter' => [
                                    'input' => ['$objectToArray' => '$users'],
                                    'cond' => [
                                        '$regexMatch' => [
                                            'input' => '$$this.k',
                                            'regex' => '14' // 替换为实际需要的键名匹配正则
                                        ]
                                    ]
                                ]
                            ]
                        ],
                        0
                    ]
                ]
            ],
            ['invoice_id' => 2]
        ]
    ];
    $result = $collection->find($filter, $option);
    

注意:非必要不使用模糊匹配键名的写法,该写法需要逐行做表达式计算,无法命中索引,数据量大时查询性能会非常差。固定键判断优先使用$exists方案。

内容的提问来源于stack exchange,提问作者Shail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:33:29