有没有办法计算mongodb中的字段名称?我有一个mongo文档数据库,其中包含其他嵌入文档。以下是数据可能的示例。
{
"incident": "osint181",
"summary":"Something happened",
"actor": {
"internal": {
"motive": [
"Financial"
],
"notes": "",
"role": [
"Malicious"
],
"variety": [
"Cashier"
]
}
}
}
另一份文件可能如下所示:
{
"incident": "osint182",
"summary":"Something happened",
"actor": {
"external": {
"motive": [
"Financial"
],
"notes": "",
"role": [
"Malicious"
],
"variety": [
"Hacker"
]
}
}
}
如您所见,演员在第二个文档中已从内部更改为外部。我希望能够做的是计算每种类型演员的事件数量。我的第一次尝试看起来像这样:
db.public.aggregate( { $group : { _id : "$actor", count : { $sum : 1 }}} );
但是这给了我整个子文档,并且计数反映了有多少文档完全相同。相反,我希望得到内部计数和外部计数等。是否有一种优雅的方式来做到这一点?如果不优雅,有人可以给我一个肮脏的方式吗?
答案 0 :(得分:1)
此类问题的最佳选择是使用mongoDB的map-reduce,它允许您遍历mongoDB文档的所有键,并且您可以轻松地添加复杂的逻辑。在此处查看地图缩小示例:http://docs.mongodb.org/manual/applications/map-reduce/
答案 1 :(得分:1)
这是我根据Devesh的暗示得出的答案。我创建了一个map函数,它查看actor的值,并使用我定义的isEmptyObject函数检查文档是否为空JSON对象。然后我使用mapReduce来检查集合并检查action字段是否为空。如果对象不是空的,而不是返回键的值,我返回键本身,它将被命名为internal或external,或者其他。
这里的魔力是mapReduce中的范围调用,这使得我的isEmptyObject在mapReduce的范围内。结果写入一个名为temp的集合。在从临时收藏中收集我想要的信息之后,我放弃它。
var isEmptyObject = function(obj) {
for (var name in obj) {
return false;
}
return true;
};
var mapFunction = function() {
if (isEmptyObject(this.action)) {
emit("Unknown",1); }
else {
for (var key in this.actor) { emit(key,1); } } };
var reduceFunction = function(inKeys,counter) {
return Array.sum(counter); };
db.public.mapReduce(mapFunction, reduceFunction, {out:"temp", scope:{isEmptyObject:isEmptyObject}} );
foo = db.temp.aggregate(
{ $sort : { value : -1 }});
db.temp.drop();
printjson(foo)