热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MongoDBMapReduce功能简单使用

最近在做搜索的查询日志的统计分析,对每一条查询统计日志,我将其解析出来后以特定字段格式存在mongodb中,定时调度做些统计分析。其中有个需求是,统计某个时间段(每天、每周、每月)各个query的查询次数,展示上就是热门查询query了。考虑到处理的数据量

最近在做搜索的查询日志的统计分析,对每一条查询统计日志,我将其解析出来后以特定字段格式存在mongodb中,定时调度做些统计分析。其中有个需求是,统计某个时间段(每天、每周、每月)各个query的查询次数,展示上就是热门查询query了。考虑到处理的数据量不会很大,解决方法也可以简单来之。我现在使用的方法就是mongodb的MapReduce功能,其实这个需求也可以认为是个group操作,而mongodb的group功能就是基于MapReduce的,但group对结果集的大小是有限制的。本文就针对一个示例介绍一下mongodb MapReduce功能。

语法介绍

MapReduce是mongodb中的一个Command,它的语法格式如下:

db.runCommand(
 false>]
   [, finalize : ]
   [, scope : ]
   [, verbose : true]
);

对于该Command,必有的3个参数我就不解释了。对于可选参数,这里简要说明如下:
(1) query是很常用的,它用来在map阶段过滤查询条件的以限定MapReduce操作的记录范围。
(2) 和query相关的还有sort和limit,我起初以为它俩是用在reduce阶段,实际上和query一起用在map阶段。
(3) mongodb默认是创建一个临时的collection存储MapReduce结果,当客户端连接关闭或者显示使用collection.drop(),这个临时的collection会被删除掉。这也就说,默认的keeptemp是false,如果keeptemp为true,那么结果collection就是永久的。当然,生成的collection名称并不友好,所以可以指定out表明永久存储的collection的名称(这时不需要再指定keeptemp)。当指定out时,并不是将执行结果直接存储到out,而是同样到临时collection,之后如果out存在则drop掉,最后rename临时collection为out。
(4) finalize:当MapReduce完成时应用到所有结果上,通常不怎么使用。
(5) verbose:提供执行时间的统计信息。
执行结果的格式如下:

{ result : ,
  counts : input :  ,
       emit  : ,
       output :  ,
  timeMillis : ,
  ok : <1_if_ok>,
  [, err : ]
}

更常用的MapReduce命令的helper是:

 db.collection.mapReduce(mapfunction,reducefunction[,options]);

map函数的定义如下,map函数内使用this来操作当前行表示的对象,并且需要使用emit(key,value)方法来向reduce提供参数:

 function map(void) -> void

reduce函数定义如下,reduce的key就是emit(key,value)的key,value_array是同个key对应的多个value数组:

 function reduce(key, value_array) -> value

MapReduce得到的collection的格式是“_id”:key,”value”:。

应用示例

这里给出一个假想的无意义的示例,主要是为了说明mongodb MapReduce的使用。每条记录的schema是“query”:,”cnt”:,”year”:,”month”=>。这个schema的cnt是不需要的,因为每条查询query的cnt都是1,但这里想要稍微复杂一些条件。下面是可在mongodb shell中执行的MapReduce脚本。

map = function() emit(this.query, this.cnt);;
reduce = function(key , vals) {
        var sum = 0;
        for(var i in vals) sum += vals[i];
        return sum;
};
res = db.log_info.mapReduce(map,reduce,{"query":"year":2010});

执行结果如下:

{
        "result" : "tmp.mr.mapreduce_1284794393_2",
        "timeMillis" : 72,
        "counts" : "input" : 1000,
                "emit" : 1000,
                "output" : 113,
        "ok" : 1,
}

对于”result”,它是生成的临时collection名称,这个名称的命名规则是:”tmp.mr.mapreduce_”+time(0)+”_”+(jobNumber++)
执行db[res.result].find()得到:

"_id" : "a", "value" : 521
"_id" : "aa", "value" : 128
"_id" : "aaa", "value" : 40
"_id" : "aaaa", "value" : 4
"_id" : "aaab", "value" : 9
"_id" : "aaac", "value" : 13
"_id" : "aab", "value" : 45
"_id" : "aaba", "value" : 5
"_id" : "aabb", "value" : 14
"_id" : "aabc", "value" : 20
"_id" : "aac", "value" : 39
"_id" : "aaca", "value" : 6
"_id" : "aacb", "value" : 2
"_id" : "aacc", "value" : 5
"_id" : "ab", "value" : 65
"_id" : "aba", "value" : 37
"_id" : "abaa", "value" : 12
"_id" : "abab", "value" : 13
"_id" : "abac", "value" : 10
"_id" : "abb", "value" : 42
Java客户端API使用

和JS脚本一样,mongodb Java客户端提供了两个MapReduce接口,分别是:

public MapReduceOutput mapReduce( String map , String reduce , String outputCollection , DBObject query );
public MapReduceOutput mapReduce( DBObject command );

MapReduceOutput实现如下:

public class MapReduceOutput {
?
    MapReduceOutput( DBCollection from , BasicDBObject raw )_collname = raw.getString( "result" );
        _coll = from._db.getCollection( _collname );
        _counts = (BasicDBObject)raw.get( "counts" );
?
    public DBCursor results()return _coll.find();
?
    public void drop()_coll.drop();
?
    public DBCollection getOutputCollection()return _coll;
?
    final String _collname;
    final DBCollection _coll;
    final BasicDBObject _counts;
}

所以,可以调用MapReduceOutput.results()得到DBCursor做后续处理,比如在我的应用场景里,根据value值做降序排序并取limit 1000以得到最热门的一些query。
由于Javascript引擎设计上的限制,当前的mongodb MapReduce还只是单线程执行,mongodb也在计划解决这个问题。如果需要多线程处理,可以考虑shard或者在客户端代码控制处理。


推荐阅读
  • MongoDB——聚合操作详解
    聚合(Aggregation)为集合文档数据提供各种处理数据方法,并返回计算结果。MongoDB提供了3种方式来执行聚合命令࿱ ... [详细]
  • 如何在U8系统中连接服务器并获取数据
    本文介绍了如何在U8系统中通过不同的方法连接服务器并获取数据,包括使用MySQL客户端连接实例的方法,如非SSL连接和SSL连接,并提供了详细的步骤和注意事项。 ... [详细]
  • 在处理木偶评估函数时,我发现可以顺利传递本机对象(如字符串、列表和数字),但每当尝试将JSHandle或ElementHandle作为参数传递时,函数会拒绝接受这些对象。这可能是由于这些句柄对象的特殊性质导致的,建议在使用时进行适当的转换或封装,以确保函数能够正确处理。 ... [详细]
  • 本文探讨了如何利用 jQuery 的 JSONP 技术实现跨域调用外部 Web 服务。通过详细解析 JSONP 的工作原理及其在 jQuery 中的应用,本文提供了实用的代码示例和最佳实践,帮助开发者解决跨域请求中的常见问题。 ... [详细]
  • 将JavaScript文件嵌入HTML文档是Web开发中的基本操作。常见的方法是通过在HTML文件中使用``标签来引用外部的.js文件。这种方法不仅保持了代码的整洁性,还便于管理和维护。此外,还可以利用模块化脚本和异步加载技术进一步提升页面性能。 ... [详细]
  • 本文探讨了如何通过检测浏览器类型来动态加载特定的npm包,从而优化前端性能。具体而言,仅在用户使用Edge浏览器时加载相关包,以提升页面加载速度和整体用户体验。此外,文章还介绍了实现这一目标的技术细节和最佳实践,包括使用User-Agent字符串进行浏览器识别、条件加载策略以及性能监控方法。 ... [详细]
  • 在 Angular Google Maps 中实现图片嵌入信息窗口的功能,可以通过使用 `@agm/core` 库来实现。该库提供了丰富的 API 和组件,使得开发者可以轻松地在地图上的信息窗口中嵌入图片。本文将详细介绍如何配置和使用这些组件,以实现动态加载和显示图片的功能。此外,还将探讨一些常见的问题和解决方案,帮助开发者更好地集成这一功能。 ... [详细]
  • 在TypeScript中,我定义了一个名为 `Employee` 的接口,其中包含 `id` 和 `name` 属性。为了使这些属性可选为空,可以通过使用 `| null` 或 `| undefined` 来扩展其类型定义。例如,`id: number | null` 表示 `id` 可以是数字或空值。这种类型的灵活性在处理不确定的数据时非常有用,可以提高代码的健壮性和可维护性。 ... [详细]
  • 我有一个包含多个URL的数组。首先,需要同步获取数组中的第一个和第二个URL,当其中任意一个请求完成时,再继续处理第三个URL。这种按序获取的方式可以确保数据的正确性和完整性,避免因并发请求导致的数据混乱。 ... [详细]
  • 本文探讨了如何在 Google Sheets 中通过自定义函数实现 AJAX 调用。具体介绍了编写脚本的方法,以便在电子表格中发起 AJAX 请求,从而实现数据的动态获取与更新。这种方法不仅简化了数据处理流程,还提高了工作效率。 ... [详细]
  • MyJGUI 0.7.3:强大的MySQL管理工具最新版发布
    MyJGUI 0.7.3 是一款基于 Java 的 MySQL 数据库管理工具的最新版本。此更新引入了新的键盘快捷键,并对用户界面进行了多项改进,提升了用户体验和操作效率。此外,该版本还优化了性能,增强了稳定性和安全性,为数据库管理员提供了更加便捷和高效的管理工具。 ... [详细]
  • Hadoop的分布式架构改进与应用
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 阿里云大数据计算服务MaxCompute (原名 ODPS)
     MaxCompute是阿里EB级计算平台,经过十年磨砺,它成为阿里巴巴集团数据中台的计算核心和阿里云大数据的基础服务。去年MaxCompute做了哪些工作,这些工作背后的原因是什 ... [详细]
  • 本文整理了Java中org.apache.hadoop.mapreduce.lib.input.MultipleInputs.addInputPath()方法的一些代码 ... [详细]
  • MapReduce的主要应用场景  可以转化为MR任务的条件:问题必须可以拆分子问题必须独立数据结构能够满足key-value的这样的模式  常见场景: ... [详细]
author-avatar
sdfdsafgafsdf
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有