【问题标题】:Convert mapreduce query to aggregation in mongodb将mapreduce查询转换为mongodb中的聚合
【发布时间】:2014-04-29 08:50:34
【问题描述】:

以下是 mapreduce 查询:

mapper=function () {
    if (this.meta != null && this.meta.active == true && this.data != null && this.data.attributes != null && this.data.attributes.lang == "en" && this.data.attributes.geo == "us" && this.meta.client.id == "1") {
        if (this.meta.created > ISODate("2014-03-30 12:27:50")) {
            emit("querisAddedSinceLastWeek", {
                "count": 1
            });
        }
        if (this.data.expectedResults == null && this.data.attributes.lang == "en" && this.data.attributes.geo == "us" && this.meta.client.id == "1") {
            emit("queriesWithExpectedResultsCount", {
                "count": 1
            });
        }
        if (this.data.attributes.lang == "en" && this.data.attributes.geo == "us" && this.meta.client.id == "1" && this.meta.active == true) {
            emit("totalActiveQueriesCount", {
                "count": 1
            });
        }
    }
}

reducer=function (k, v) {
    counter = 0;
    for (i = 0; i < v.length; i++) {
        counter += v[i].count;
    }
    return {
        "count": counter
    }
}

db['ARTDocument.dev'].mapReduce(mapper,reducer,{out:{inline:1}});

在这个查询中,一些条件对于所有 3 个查询都是通用的,并且每个查询只有一个条件。如果可能,我想在一个查询中触发这些查询,如果可能的话,使用 monodb 中的聚合框架。 我希望将这个确切的查询写在 mongodb 的聚合框架中。

这个我试过了,但是没用。

db['ARTDocument.dev'].aggregate(

    {
        $match: {
            "meta.active": true,
            "meta.client.id": 1,
            "data.attributes.lang": "en",
            "data.attributes.geo": "us"
        }
    }, {
        $group: {
            _id: {
                $cond: [{
                        $lt: ["meta.created", ISODate("2014-03-30 12:27:50")]
                    },
                    "querisAddedSinceLastWeek",
                    "null"
                ]
            },
            count: {
                $sum: 1
            }
        }
    }, {
        $group: {
            _id: {
                $ifNull: ["data.expectedResults", "queriesWithoutExpectedResultsCount"]
            },
            count: {
                $sum: 1
            }
        }
    }

)

【问题讨论】:

  • 我们通常不会为提出要求的人按需进行代码转换。如果您可以向我们展示您迄今为止所做的尝试以及您遇到的问题,我相信我们可以帮助您
  • 我在试用期间编辑了问题...请帮助我...
  • 发布示例数据文档并说明预期输出将增加此问题得到回答的机会。

标签: java mongodb mapreduce aggregation-framework


【解决方案1】:

您对流程有正确的总体概念,但您的结构略有偏差。

你的第一阶段,$match条件有资格被计入就可以了。

match = {$match: {
         "meta.active": true,
         "meta.client.id": 1,
         "data.attributes.lang": "en",
         "data.attributes.geo": "us"
        }

您的下一个阶段是 $group,这是应该的,但您并没有完全围绕正确的键进行分组。由于您想获得所有合格文档的总数,因此您应该将_id 分组为常量,并根据条件评估是否为真,将$sum 设置为 1 或 0。

group = {$group: {
         _id: null,
         querisAddedSinceLastWeek : { $sum : {$cond: [
                    { $gt : [ meta.created, ISODate("2014-03-30 12:27:50") ] },
                    1, 0 ] }
         },
         queriesWithExpectedResultsCount: { $sum:
                    { $eq : [ data.expectedResults, null ] }, 
                    1, 0 ] }
         },
         totalActiveQueriesCount: { $sum : 1 }
} }

您的地图函数有 很多 不必要的(冗余)条件,通常最好表达您的实际需求 - 但它当前所做的是总结所有活动查询,并获得自上周以来的查询总和,以及具有空 data.expectedResults 的查询。

完全聚合,定义了以上两个阶段:

db['ARTDocument.dev'].aggregate( match, group );

【讨论】:

    猜你喜欢
    • 2020-08-20
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 2018-01-08
    • 1970-01-01
    相关资源
    最近更新 更多