MongoDb mapreduce

       周四脑袋发热,突然想获取文档中id的最大值,发现mongodb中没有sql中max聚合函数,只能通过对整个文档使用sort和limit(1)获取最大值。感觉很不

爽,突然想起map-reduce不就是聚合用的吗,于是乎就写了这个map-reduce的聚合功能。我的js一般,mongodb初学,很多东西没弄明白,我将实现方式和疑问在这里记录下来,

意识要和大家分享下,一是避免初学者和我犯同样的错误,而是希望有人解答我的疑问。

我在这里利用map-reduce主要实现了 max 和 sum 功能,其他功能的实现类似。直接上代码了

using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Mongo.Util
{
    public static class Extension
    {
        /// <summary>
        /// 获取集合文档数量
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <returns></returns>
        public static Dictionary<string, int> CountKeyOfCollection<T>(this MongoCollection<T> collection)
        {
            var map = @"function() {" +
      "    for (var key in this) {" +
      "        emit(key, { count : 1 });" +
      "    }" +
      "}";

            var reduce = @"function(key, emits) {" +
                "    total = 0;" +
                "    for (var i in emits) {" +
                "        total += emits[i].count;" +
                "    }" +
                "    return { count : total };" +
                "}";
            var finalize = @"";
            var mra = new MapReduceArgs();
            mra.MapFunction = map;
            mra.ReduceFunction = reduce;
            var mr = collection.MapReduce(mra);
            Dictionary<string, int> dict = new Dictionary<string, int>();
            foreach (var document in mr.GetResults())
            {
                var json = document.ToJson();
                JObject obj = JsonConvert.DeserializeObject<JObject>(json);
                var _id = obj["_id"];
                var count = obj["value"]["count"];
                dict.Add(_id.ToString(), Convert.ToInt32(count));
            }
            return dict;

        }

        /// <summary>
        /// 这个错误,怎么获取当前key 的value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        public static void Max<T>(this MongoCollection<T> collection)
        {
            //怎么获取当前key 的value
            var map = @"function(){
                              for(var key in this){
                                     emit(key,value);
                            }                
                        }";
            var reduce = @"function(key,values){
                var max=values[0];
                 var tmp;
                    for(var i =1;i<values.lenght;i++)
                    {
                        tmp=values[i];
                        if(max<tmp)
                             max=tmp;
                    }
                  return max;
                }";
            var finalize = "";
            var mra = new MapReduceArgs();
            mra.MapFunction = map;
            mra.ReduceFunction = reduce;
            var mr = collection.MapReduce(mra);
        }
        /// <summary>
        /// 对指定key 求 max
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="field">key大小写敏感</param>
        public static void Max<T>(this MongoCollection<T> collection, string field)
        {
            var map = "function(){ "
                            + "for(var key1 in this) "
                             + "                  { "
                             + "                    if(key1.toLowerCase()=='"+field.ToLower()+"')"
                             + "                           {"
                             + "                              emit(key1,this."+field+");"
                            + "                           }"
                            + "             }"
                             + "                   }";

            var reduce = @"function(key,values){
                            var maxTmp=values[0];
                             for(var i=1;i<values.length;i++)
                            {
                                if(maxTmp<values[i])
                                    maxTmp=values[i];
                           }
                        return {key:key,max:maxTmp};
                }";
            var finalize = "";
            var mra = new MapReduceArgs();
            mra.MapFunction = map;
            mra.ReduceFunction = reduce;
            var mr = collection.MapReduce(mra);
        }
        /// <summary>
        /// 对指定key求和
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="field">key大小写敏感</param>
        public static void Sum<T>(this MongoCollection<T> collection, string field)
        {
            var map = "function(){ "
                            + "for(var key1 in this) "
                             + "                  { "
                             + "                    if(key1.toLowerCase()=='" + field.ToLower() + "')"
                             + "                           {"
                             + "                              emit(key1,this." + field + ");"
                            + "                           }"
                            + "             }"
                             + "                   }";

            var reduce = @"function(key,values){
                         var ret= {key:key,sum:values.reduce(function(prev, cur, index, array){return prev + cur;})};    
                        return ret;
                }";
            var finalize = "";
            var mra = new MapReduceArgs();
            mra.MapFunction = map;
            mra.ReduceFunction = reduce;
            var mr = collection.MapReduce(mra);
        }

        /// <summary>
        /// 对指定key求和
        /// 怎么判断value类型 $type=2 js判断方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="field">key大小写敏感</param>
        public static void Sum2<T>(this MongoCollection<T> collection, string field)
        {
            var map = "function(){ "
                            + "for(var key1 in this) "
                             + "                  { "
                             + "                    if(key1.toLowerCase()=='" + field.ToLower() + "')"
                             + "                           {"
                             + "                              emit(key1,this." + field + ");"
                            + "                           }"
                            + "             }"
                             + "                   }";

            var reduce = @"function(key,values){
                         var ret= {key:key,sum:Array.sum(values)};    
                        return ret;
                }";
            var finalize = "";
            var mra = new MapReduceArgs();
            mra.MapFunction = map;
            mra.ReduceFunction = reduce;
            var mr = collection.MapReduce(mra);
        }

        /// <summary>
        /// 这个错误,到底this 能获取什么 key value ????
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        public static void Sum<T>(this MongoCollection<T> collection)
        {
            //关键问题怎么获取当前key 对应的value 怎么解决
            var map = "function(){ "
                            +"var i=0;"
                             + "for(var key1 in this) "
                              + "                  { "
                              + "                              emit(key1,value[i]);" 
                              +"i++;"
                             + "             }"
                              + " }";

            var reduce = @"function(key,values){
                         var ret= {key:key,sum:values.reduce(function(prev, cur, index, array){return prev + cur;})};    
                        return ret;
                }";
            var finalize = "";
            var mra = new MapReduceArgs();
            mra.MapFunction = map;
            mra.ReduceFunction = reduce;
            var mr = collection.MapReduce(mra);
        }


    }
}

 

 

注意:上边我说明错误的方法,是我希望高手指点的,这里只有max和sum方法能用,不要怀疑我的能力哦。

我想请教大家,map reduce中的this 到底是什么东东,当前文档,有什么属性可以使用, 我怎么看着当前key对应的value

参考学习资料:http://www.cnblogs.com/loogn/archive/2012/02/09/2344054.html

  http://docs.mongodb.org/manual/reference/command/mapReduce/

posted @ 2015-03-21 12:55  ‖风之殇‖  阅读(458)  评论(0编辑  收藏  举报