假设您在mongodb中有一个可变大小的地图。 如何获得仅具有特定地图大小的文档,例如> 2?
NA.Count = function(x)
{
return(sum(is.na(x)))
}
Row.NA.Count = apply(MAT,1,NA.Count)
Idx = Row.NA.Count == ncol(MAT)
MAT = MAT[!Idx,]
答案 0 :(得分:2)
使用MongoDB 3.6及更高版本:
在查询中使用 $expr
运算符,这允许您使用聚合框架运算符,尤其是转换地图的 $objectToArray
运算符subocument到一组键值,即
{ 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
}
}