用MongoDB实现MapReduce
MapReduce 是 Google 在 2004 年发布的一个软件框架,用于支持大规模数据的分布式计算,详情请看这里。
MongoDB 是一个开源的面向文档的 NoSQL 数据库系统,使用 C++ 编写,详情请看这里。
1. 安装 MangoDB
首先请按照官方这个文档安装 MongoDB 数据库,在本文中,我们是在 Mac OS X 下安装并测试无误。
我使用 sudo port install mongodb 命令来安装 MongoDB ,唯一碰到的一个问题是 xcode 的版本问题,升级到 xcode 的最新版本就好了。
2. 运行 MongoDB
启动 MongoDB 是很简单的,只需要在终端窗口中执行 mogod 即可。
默认 MongoDB 是运行在 27017 端口上,使用 /data/db 作为默认目录来存放数据(我们已经在第一步就创建了这个目录)
如果你修改这些默认的配置,你可以通过命令行参数来进行修改:
mongod --port [your_port] --dbpath [your_db_file_path]你需要确认的是数据目录必须已经存在并且在 mongodb 首次启动时该目录下没有其他文件。
3. 启动 MongoDB 交互环境
我们可以启动 MongoDB 交互环境来连接到 MongoDB 服务器,并在命令行中直接运行 MongoDB 命令。
在同一台机器上,你只需要简单的执行 mongo 就可以进入交互环境,如果想要连接不同机器上的 MongoDB 服务器,你可以使用下面的参数来指定目标服务器的IP地址和端口:
mongo [ip_address]:[port]
例如 : mongo localhost:4000
4. 创建数据库
接下来在交互环境中执行下面命令来创建数据库:
use library
上述命令创建了一个名为 library 的数据库。
然后我们可以通过下面的命令来查看刚创建的数据库,下面命令列出系统中所有的数据库:
show dbs;
你会注意到,你刚创建的数据库并没有列出来,这是因为 MongoDB 只有在需要的时候才会创建数据库,因此你需要往数据库里添加点数据。
5. 往数据库中插入数据
首先我们通过以下命令创建两本书:
> book1 = {name : "Understanding JAVA", pages : 100}
> book2 = {name : "Understanding JSON", pages : 200}
然后将这两本书保持到名为 books 的集合中:
> db.books.save(book1)
> db.books.save(book2)
上述命令将在 library 数据库中创建一个名为 books 的集合(也就是SQL数据库中的表),下面命令将列出我们刚添加的两本书:
> db.books.find();
{ "_id" : ObjectId("4f365b1ed6d9d6de7c7ae4b1"), "name" : "Understanding JAVA", "pages" : 100 }
{ "_id" : ObjectId("4f365b28d6d9d6de7c7ae4b2"), "name" : "Understanding JSON", "pages" : 200 }
添加更多的记录:
> book = {name : "Understanding XML", pages : 300}
> db.books.save(book)
> book = {name : "Understanding Web Services", pages : 400}
> db.books.save(book)
> book = {name : "Understanding Axis2", pages : 150}
> db.books.save(book)
6. 编写 Map 函数
接下来我们编写一个搜索功能,用来查找超过250页的图书:
> var map = function() { var category; if ( this.pages >= 250 ) category = 'Big Books'; else category = "Small Books"; emit(category, {name: this.name}); };
所返回的结果:
{"Big Books",[{name: "Understanding XML"}, {name : "Understanding Web Services"}]);
{"Small Books",[{name: "Understanding JAVA"}, {name : "Understanding JSON"},{name: "Understanding Axis2"}]);
7. 编写 Reduce 函数
> var reduce = function(key, values) { var sum = 0; values.forEach(function(doc) { sum += 1; }); return {books: sum}; };
8. 在 books 集合中运行 MapReduce
> var count = db.books.mapReduce(map, reduce, {out: "book_results"}); > db[count.result].find() { "_id" : "Big Books", "value" : { "books" : 2 } } { "_id" : "Small Books", "value" : { "books" : 3 } }
上述结果表明我们有两本大书和三本小书。
利用 MongoDB 交互环境可以做任何事情,用 Java 也一样,但是你需要下载一些必须的jar包。
下面是 Java 的源码:
import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.MapReduceCommand; import com.mongodb.MapReduceOutput; import com.mongodb.Mongo; public class MongoClient { /** * @param args */ public static void main(String[] args) { Mongo mongo; try { mongo = new Mongo("localhost", 27017); DB db = mongo.getDB("library"); DBCollection books = db.getCollection("books"); BasicDBObject book = new BasicDBObject(); book.put("name", "Understanding JAVA"); book.put("pages", 100); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding JSON"); book.put("pages", 200); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding XML"); book.put("pages", 300); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding Web Services"); book.put("pages", 400); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding Axis2"); book.put("pages", 150); books.insert(book); String map = "function() { "+ "var category; " + "if ( this.pages >= 250 ) "+ "category = 'Big Books'; " + "else " + "category = 'Small Books'; "+ "emit(category, {name: this.name});}"; String reduce = "function(key, values) { " + "var sum = 0; " + "values.forEach(function(doc) { " + "sum += 1; "+ "}); " + "return {books: sum};} "; MapReduceCommand cmd = new MapReduceCommand(books, map, reduce, null, MapReduceCommand.OutputType.INLINE, null); MapReduceOutput out = books.mapReduce(cmd); for (DBObject o : out.results()) { System.out.println(o.toString()); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
OSCHINA 原创翻译自:facilelogin