mongodb-15.MapReduce,runCommand

MapReduce命令

>db.collection.mapReduce(
   function() {emit(key,value);},  //map 函数
   function(key,values) {return reduceFunction},   //reduce 函数
   {
      out: collection,
      query: document,
      sort: document,
      limit: number
   }
)

在 mapReduce 命令中要实现两个函数,分别是 map 函数和 reduce 函数,其中 map 函数调用 emit(key, value),遍历集合中的所有记录,并将 key 与 value 传递给 reduce 函数进行处理

参数说明如下:

map 函数:一个 javascript 函数,它用一个键映射一个值并发出一个键值对;
reduce 函数:一个 javascript 函数,用于减少或分组具有相同键的所有文档;
out:指定 map-reduce 查询结果的位置;
query:指定用于选择文档的可选选择条件;
sort:指定可选的排序条件;
limit:指定要返回的最大文档数(可选)。

数据准备

>db.user.insertMany([
  {"name" : "鲁迅","book" : "呐喊","price" : 38.0,"publisher" : "人民文学出版社"},
  {"name" : "曹雪芹","book" : "红楼梦","price" : 22.0,"publisher" : "人民文学出版社"},
  {"name" : "钱钟书","book" : "宋诗选注","price" : 99.0,"publisher" : "人民文学出版社"},
  {"name" : "钱钟书","book" : "谈艺录","price" : 66.0,"publisher" : "三联书店"},
  {"name" : "鲁迅","book" : "彷徨","price" : 55.0,"publisher" : "花城出版社"}
  ])
<{ acknowledged: true,
  insertedIds: 
   { '0': ObjectId("63ac0f702574a3d57b1902ae"),
     '1': ObjectId("63ac0f702574a3d57b1902af"),
     '2': ObjectId("63ac0f702574a3d57b1902b0"),
     '3': ObjectId("63ac0f702574a3d57b1902b1"),
     '4': ObjectId("63ac0f702574a3d57b1902b2") } }

当采用mapReduce的时候,提示已经过期了

>db.user.mapReduce(
  function(){emit(this.name,this.price)},
  function(key,value){return Array.sum(value)},
  {out:'totalPrice'}
  )
 <'DeprecationWarning: Collection.mapReduce() is deprecated. Use an aggregation instead.\nSee https://docs.mongodb.com/manual/core/map-reduce for details.'

以上是MongoDB Compass工具执行的时候的提示

用shell连接linux后,进入mongo后,执行

rsb:PRIMARY> db.user.mapReduce(
...   function(){emit(this.name,this.price)},
...   function(key,value){return Array.sum(value)},
...   {out:'totalPrice'}
...   )
{
        "result" : "totalPrice",
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1672221336, 5),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1672221336, 5)
}
rsb:PRIMARY> 

执行成功以后,我们通过show tables发现,多了totalPrice集合

db.totalPrice.find()
{ _id: '鲁迅', value: 93 }
{ _id: '钱钟书', value: 165 }
{ _id: '曹雪芹', value: 22 }

emit 函数用于生成 key-value 数据集合,emit(key, value); OR emit(key, {v1:v1, v2:v2});

第一个参数是key, 第二个参数是key对应的数据集合

emit 函数主要实现的分组,接收两个参数,第一个参数表示分组的分段,第二个参数表示要统计的数据,减少做特定的数据处理操作,接收两个参数,对应的 emit 方法的两个参数,此处使用了 Array 中的sum 对 price 分段进行自加处理,options 中定义了将结果输出的集合,届时我们将在此集合中去查询数据,很少情况下,这个集合即使在数据库重启后也会保留,并保留集合中的数据

mongo数据库重启后,totalPrice集合是否依然存在,待验证

var map=function(){emit(this.name,this.book)}
var reduce=function(key,value){return value.join(',')}
var options={out:"books"}
db.user.mapReduce(map,reduce,options);
{ "result" : "books", "ok" : 1 }

db.books.find()
{ "_id" : "鲁迅", "value" : "彷徨,呐喊" }
{ "_id" : "曹雪芹", "value" : "红楼梦" }
{ "_id" : "钱钟书", "value" : "谈艺录,宋诗选注" }

疑问:是否可以在mongo中将这些命令写入到js函数中,由java去直接调用js函数呢?

查询每个人体重在¥ 40以上的书:

var map=function(){emit(this.name,this.book)}
var reduce=function(key,value){return value.join(',')}
var options={query:{price:{$gt:40}},out:"books"}
db.user.mapReduce(map,reduce,options);
{ "result" : "books", "ok" : 1 }

db.books.find()
{ "_id" : "鲁迅", "value" : "彷徨" }
{ "_id" : "钱钟书", "value" : "谈艺录,宋诗选注" }

runCommand 命令

语法

db.runCommand(
               {
                 mapReduce: <collection>,
                 map: <function>,
                 reduce: <function>,
                 finalize: <function>,
                 out: <output>,
                 query: <document>,
                 sort: <document>,
                 limit: <number>,
                 scope: <document>,
                 jsMode: <boolean>,
                 verbose: <boolean>,
                 bypassDocumentValidation: <boolean>,
                 collation: <document>
               }
             )

在这里插入图片描述
如下操作,表示执行MapReduce操作重新统计的集合限制返回条数,限制返回条数之后再进行统计操作,如下:

var map=function(){emit(this.name,this.book)}
var reduce=function(key,value){return value.join(',')}
db.runCommand({mapreduce:'user',map,reduce,out:"books",limit:4,verbose:true})
db.books.find()

结果

{ "_id" : "鲁迅", "value" : "呐喊" }
{ "_id" : "曹雪芹", "value" : "红楼梦" }
{ "_id" : "钱钟书", "value" : "谈艺录,宋诗选注" }

finalize 操作表示最终处理函数,如下:

f1 第一个参数键表示emit中的第一个参数,第二个参数表示reduce的执行结果,我们可以在f1中对这个结果进行再处理

var f1 = function(key,reduceValue){var obj={};obj.author=key;obj.books=reduceValue; return obj}
var map=function(){emit(this.name,this.book)}
var reduce=function(key,value){return value.join(',')}
db.runCommand({mapreduce:'user',map,reduce,out:"books",finalize:f1})
db.books.find()

{ "_id" : "鲁迅", "value" : { "author" : "鲁迅", "books" : "彷徨,呐喊" } }
{ "_id" : "曹雪芹", "value" : { "author" : "曹雪芹", "books" : "红楼梦" } }
{ "_id" : "钱钟书", "value" : { "author" : "钱钟书", "books" : "谈艺录,宋诗选注" } }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值