MongoDB MapReduce,仅在count> gt时返回1

时间:2016-12-01 10:51:07

标签: javascript mongodb mapreduce mongodb-query aggregation-framework

我在MongoDB中有数据。一个对象的结构如下:

{
    "_id" : ObjectId("5395177980a6b1ccf916312c"),
    "institutionId" : "831",
    "currentObject" : {
          "systemIdentifiers" : [
            {
                "value" : "24387",
                "system" : "ABC"
            }]
      }
}

我必须知道有多少个对象具有相同的 institutionId systemIdentifiers [0] .value ,并且只想返回以这种方式重复的对象。 为此,我将这些ID分组并计算出现次数。

count 大于1时,应返回对象(一对ID)。

这是一块使用MapReduce进行分组的代码。

var map = function() {
    var key = this.institutionId;
    var val = this.currentObject.systemIdentifiers[0].value;
    emit({"institutionId":key,"workId":val}, {count:1});     
};
var reduce = function(key, values) {
    var count = 0;
    values.forEach(function(v) {
        count += v['count'];
    });
    return {count: count};
}
db.name.mapReduce(map, reduce, {out: "grouped"})
db.grouped.find()

为了只获得数量大于1的人,我做

db.grouped.aggregate([{$match:{"value.count":{$gt: 1}}}])

然后是

后面的示例结果
{
    "_id" : {
        "institutionId" : "1004",
        "workId" : "591426"
    },
    "value" : {
        "count" : 2
    }
}

但我很好奇是否可以通过将MapReduce作为一个语句来完成它。就像添加终结者一样。

2 个答案:

答案 0 :(得分:2)

如果有一个文件有一个密钥,那么永远不会进入reduce ,被认为已经减少了,那就是MongoDB map-reduce的行为:

  

MongoDB will not call the reduce function for a key that has only a single value.

使用finalzie也没有多大帮助,即如果在最终功能中你执行了BaseMenuModel,那么结果中你将获得None(而不是1)。

我担心使用(一个)map-reduce,结果中的计数为1的文档将 alwasy ,因为它们是从地图中启动的。

您可以在链中使用2个地图缩小操作,在第二个地图中,您不会发出具有计数的文档<但是这些并不认为它比你的例子中的额外查询更好。

答案 1 :(得分:1)

更好,更简单,更有效的方法是使用聚合框架,您可以使用 $arrayElemAt 等运算符从数组返回第一个子文档,然后使用<强> $group 管道来汇总计数。然后,您可以放置​​ $match 管道,根据给定的条件过滤结果。

以下示例显示了这种更快的方法:

db.name.aggregate([
    {
        "$project": {
            "key": "$institutionId",
            "val": {
                "$arrayElemAt": ["$currentObject.systemIdentifiers", 0]
            }
        }
    },
    {
        "$group": {
            "_id": {
                "institutionId": "$key",
                "workId": "$val.value"
            },
            "count": { "$sum": 1 }
        }
    },
    { "$match": { "count": { "$gt": 1 } } }
])