MongoDB如何查询fieldValues动态键下包含指定ObjectId的文档
解决方案
你可以通过$objectToArray操作符将fieldValues动态转为键值对数组,再匹配数组中是否包含目标ObjectId,所有逻辑均在MongoDB端执行,无需后端全量拉取筛选:
可用查询语句
// 定义要查询的目标ObjectId const targetId = ObjectId("6148a371c13a6a0be492ebf4"); // 查询语句 db.getCollection('products').find({ $expr: { $gt: [ { $size: { $filter: { input: { $objectToArray: "$fieldValues" }, cond: { $and: [ // 可选:过滤掉fieldValues下非数组类型的字段,避免报错 { $isArray: "$$this.v" }, // 匹配当前字段的数组中是否包含目标ID { $in: [targetId, "$$this.v"] } ] } } } }, // 只要存在任意一个字段的数组包含目标ID就符合条件 0 ] } })
逻辑说明
$objectToArray: "$fieldValues"会将不确定键名的fieldValues对象转换为统一格式的键值对数组,示例转换结果为[{k: "PDV", v: ["6126938cd24a8aa3d37b4992", ObjectId("xxx")]}, {k: "DDB", v: [...]}]$filter会遍历上述键值对数组,筛选出值为数组且包含目标ID的元素- 最终判断筛选后的数组长度是否大于0,大于0则说明该文档符合查询条件
百万级数据性能优化
上述原生查询默认走全表扫描,针对百万级数据集可做如下优化:
- 若使用MongoDB 4.2及以上版本,可创建
fieldValues通配符多键索引:db.products.createIndex({ "fieldValues.$**": 1 }) - 若业务允许调整表结构,建议将
fieldValues从对象格式改为数组格式(示例:"fieldValues": [{"key": "PDV", "values": [...]}]),直接对fieldValues.values建多键索引,查询性能可提升数倍,完全满足高并发查询需求。
内容的提问来源于stack exchange,提问作者Qui-Gon Jinn
相关产品推荐
相关产品推荐

