使用 MongoDB 3.6 及更高版本:
在查询中使用 $expr 运算符,这允许您使用聚合框架运算符,特别是 $objectToArray 运算符,它将地图子文档转换为数组关键值,即
{ map: {
k1:v1,
k2:v2,
k3,v3
}}
转化为数组
{ map: [
{ k: 'k1', v: 'v1' },
{ k: 'k2', v: 'v2' },
{ k: 'k3', v: 'v3' }
]}
有了数组,你可以使用 $size 来获取长度并使用比较查询运算符 $gt 进行比较。
下面的示例显示了完整的查询:
db.test.find({
"$expr": {
"$gt": [
{ "$size": { "$objectToArray": "$map" } },
2
]
}
})
对于不支持上述运算符的 MongoDB 版本,如果您想稍后对其进行查询,则需要预先计算此类映射大小,因此请考虑创建一个新字段 "keyCount",其中包含地图子文档的键。考虑以下演示:
填充测试集合
db.test.insert([
{
"_id" : 1,
"map" : {
"k1" : "v1",
"k2" : "v2",
"k3" : "v3"
}
},
{
"_id" : 2,
"map" : {
"k1" : "v1",
"k2" : "v2"
}
}
]);
与当前设计一样,您需要一种机制来获取地图文档中所有键的计数。这可以通过 Map-Reduce 实现。以下 mapreduce 操作将使用添加的新字段 "keyCount" 填充单独的集合:
var mr = db.runCommand({
"mapreduce": "test",
"map" : function() {
var obj = this;
obj['keyCount'] = Object.keys(this.map).length;
emit(this._id, obj);
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
要获取只有特定地图大小的文档,例如 > 2,请在结果集合上运行查询:
db[mr.result].find({ "value.keyCount": { "$gt": 2 } });
地图缩减输出
/* 0 */
{
"result" : "my_collection_keys",
"timeMillis" : 7,
"counts" : {
"input" : 2,
"emit" : 2,
"reduce" : 0,
"output" : 2
},
"ok" : 1
}
查询输出
/* 0 */
{
"_id" : 1,
"value" : {
"_id" : 1,
"map" : {
"k1" : "v1",
"k2" : "v2",
"k3" : "v3"
},
"keyCount" : 3
}
}