事由:mongodb已经进行数据分片,这样就不能使用一些方法就不能使用,例如eval,$group如果尝试使用mongodb会提示

Error: {
"ok" : ,
"errmsg" : "Error: Error: can't use sharded collection from db.eval @:2:9\n",
"code" : ,
"codeName" : "BadValue"
} :

错误原因:分片服务端不支持单服务器实例方法

经过查找,分片服务器的查询和操作只能使用MapReduce或者Aggregate(聚合管道)操作,这两个mongodb的高级操作可以完成mongo的几乎所有操作。

需求:查询collection当天满足指定条件的数据,并根据数据进行每个小时的pv,uv,ui统计

collection中存放浏览器访问记录

首先我们先使用mongdb的语句把查询语句写出来,这个很关键。如果不是很了解,就去解读一下官方文档吧,一言难尽。

db.runCommand({
mapreduce:'visits',
query:{ 'sh.si':100650, _id: { $gte: ObjectId('59931a800000000000000000') }},
map:function(){
emit(
{hours:this._id.getTimestamp().getHours()},{pv:1,ip:this.ip,ui:this.ui,hours:this._id.getTimestamp().getHours()}
);
},
reduce:function(k,values){
var data = {
hours:0,
pv: 0,
ip:[],
ui:[]
};
values.forEach(function (v) {
data.hours=v.hours;
data.pv+=v.pv;
if(v.ui)
data.ui.push(v.ui);
if(v.ip)
data.ip.push(v.ip);
});
return data;
},
finalize:function(key,v){
v.hours=NumberInt(v.hours);
v.pv=NumberInt(v.pv);
if(v.ui)
v.ui=NumberInt(ArrayGroup(v.ui).uni - 1);
else
v.ui=0;
if(v.ip)
v.ip=NumberInt(ArrayGroup(v.ip).uni - 1);
else
v.ip=0;
return v;
},
out:{inline:1}
});

执行之后会得到这样的结果

/* 1 */
{
"results" : [
{
"_id" : {
"hours" : 1.0
},
"value" : {
"pv" : 1,
"ip" : 0,
"ui" : 0.0,
"hours" : 1
}
},
{
"_id" : {
"hours" : 4.0
},
"value" : {
"pv" : 1,
"ip" : 0,
"ui" : 0.0,
"hours" : 4
}
},
{
"_id" : {
"hours" : 5.0
},
"value" : {
"pv" : 1,
"ip" : 0,
"ui" : 0.0,
"hours" : 5
}
},
{
"_id" : {
"hours" : 6.0
},
"value" : {
"hours" : 6,
"pv" : 4,
"ip" : 0,
"ui" : 0
}
},
{
"_id" : {
"hours" : 7.0
},
"value" : {
"pv" : 1,
"ip" : 0,
"ui" : 0,
"hours" : 7
}
},
{
"_id" : {
"hours" : 8.0
},
"value" : {
"hours" : 8,
"pv" : 8,
"ip" : 5,
"ui" : 4
}
},
{
"_id" : {
"hours" : 9.0
},
"value" : {
"hours" : 9,
"pv" : 10,
"ip" : 3,
"ui" : 0
}
},
{
"_id" : {
"hours" : 10.0
},
"value" : {
"hours" : 10,
"pv" : 9,
"ip" : 5,
"ui" : 2
}
},
{
"_id" : {
"hours" : 11.0
},
"value" : {
"hours" : 11,
"pv" : 17,
"ip" : 9,
"ui" : 1
}
},
{
"_id" : {
"hours" : 12.0
},
"value" : {
"hours" : 12,
"pv" : 20,
"ip" : 8,
"ui" : 2
}
},
{
"_id" : {
"hours" : 13.0
},
"value" : {
"hours" : 13,
"pv" : 23,
"ip" : 5,
"ui" : 2
}
},
{
"_id" : {
"hours" : 14.0
},
"value" : {
"hours" : 14,
"pv" : 33,
"ip" : 9,
"ui" : 2
}
},
{
"_id" : {
"hours" : 15.0
},
"value" : {
"hours" : 15,
"pv" : 52,
"ip" : 14,
"ui" : 4
}
}
],
"counts" : {
"input" : NumberLong(180),
"emit" : NumberLong(180),
"reduce" : NumberLong(26),
"output" : NumberLong(13)
},
"timeMillis" : 250,
"timing" : {
"shardProcessing" : 152,
"postProcessing" : 97
},
"shardCounts" : {
"ins-cluster-01/ins-mongodb-01:27018,ins-mongodb-03:27018" : {
"input" : 90,
"emit" : 90,
"reduce" : 9,
"output" : 12
},
"ins-cluster-02/ins-mongodb-02:27019,ins-mongodb-04:27019" : {
"input" : 90,
"emit" : 90,
"reduce" : 8,
"output" : 10
}
},
"postProcessCounts" : {
"ins-cluster-01/ins-mongodb-01:27018,ins-mongodb-03:27018" : {
"input" : NumberLong(22),
"reduce" : NumberLong(9),
"output" : NumberLong(13)
}
},
"ok" : 1.0
}

results

只看results返回的数据就可以

接着就可以借助这里的js脚本移植到C#程序中

  public dynamic Today(int id)
{
//var rel = db.DataBase.Eval("show_visited_by_hours(" + id + ")").ToBsonDocument().ToDynamic();
//return rel; var query = Query.And(
Query.EQ("sh.si", id),
Query.GTE("_id", new ObjectId(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day), , , ))
);//筛选数据
var map = new BsonJavaScript(@"function () {
emit(
{hours:this._id.getTimestamp().getHours()},{pv:1,ip:this.ip,ui:this.ui,hours:this._id.getTimestamp().getHours()}
);
}");//数据按需分组 var reduce = new BsonJavaScript(@"function(k,values){
var data = {
hours:0,
pv: 0,
ip:[],
ui: []
};
values.forEach(function (v) {
data.hours=v.hours;
data.pv+=v.pv;
data.ui.push(v.ui);
data.ip.push(v.ip);
});
return data;
}
");//根据map传递参数做数据操作
var finalize = new BsonJavaScript(@"function(key,v){
v.hours=NumberInt(v.hours);
v.pv=NumberInt(v.pv);
if(v.ui)
v.ui=NumberInt(ArrayGroup(v.ui).uni - 1);
else
v.ui=NumberInt(0);
if(v.ip)
v.ip=NumberInt(ArrayGroup(v.ip).uni - 1);
else
v.ip=NumberInt(0);
return v;
}");//按照指定格式编排输出数据格式
MapReduceOptionsBuilder mrob = new MapReduceOptionsBuilder();//定义附加项MapReduceOptions
mrob.SetFinalize(finalize);
mrob.SetQuery(query);
mrob.SetOutput(MapReduceOutput.Inline);//选择直接输出结果
var rel = db.DataBase.GetCollection("visits").MapReduce(map,reduce, mrob); //提交执行MapReduce
var valuearray=rel.InlineResults;//获取执行结果集
var pvcount = ;
var ipcount = ;
var uicount = ;
var count = new List<BsonDocument>();
foreach (var vitem in valuearray)
{
pvcount+= (int)vitem["value"]["pv"];
ipcount += (int)vitem["value"]["ip"];
uicount += (int)vitem["value"]["ui"];
count.Add(vitem["value"].ToBsonDocument());
}
var result = new { pv= pvcount, ip = ipcount, ui = uicount, count = count };//按指定格式组装数据
return result.ToBsonDocument().ToDynamic();
}

过程还需要多去揣摩至于Aggregate就相对很简单了,把所有的查询对象,查询聚合使用BsonDocument做好参数格式化。

再附上一个Aggregate在C#中的使用方法,相对较容易理解。

public string func_api_site_count(int sid = , int st = , int et = , string flag = "year", string order = "pv desc")
{
var sitesday = _dbs.DataBase.GetCollection("log_sites_day");
var match = new QueryDocument();
match.AddRange(new Dictionary<string, object> {
{ "_id.day", new Dictionary<string, object> { { "$gte", st }, { "$lte", et } }},
{ "_id.sid", new Dictionary<string, object> { { "$eq", sid } }}
});
var group = new Dictionary<string, object>();
var sort = new Dictionary<string, BsonValue>();
var query = new Dictionary<string, object>();
switch (flag)
{
case "month":
query.Add("$substr", new List<object>() { "$_id.day", , });
break;
case "year":
query.Add("$substr", new List<object>() { "$_id.day", , });
break;
case "day":
query.Add("$_id.day", "$_id.day");
break;
case "week":
break;
} group.Add("_id", query);
group.Add("pv", new BsonDocument("$sum", "$pv"));
group.Add("uv", new BsonDocument("$sum", "$uv"));
group.Add("ui", new BsonDocument("$sum", "$ui"));
group.Add("ip", new BsonDocument("$sum", "$ip"));
group.Add("nuv", new BsonDocument("$sum", "$nuv"));
group.Add("area", new BsonDocument("$push", "$area"));
group.Add("rf", new BsonDocument("$push", "$rfsite"));
var groupby = new Dictionary<string, BsonValue>{
{"_id",null},
{"day",new BsonDocument("$push", "$_id")},
{"uv",new BsonDocument("$push", "$uv")},
{"pv",new BsonDocument("$push", "$pv")},
{"ui",new BsonDocument("$push", "$ui")},
{"ip",new BsonDocument("$push", "$ip")},
{"nuv",new BsonDocument("$push", "$nuv")},
{"area",new BsonDocument("$push", "$area")},
{"rfsite",new BsonDocument("$push", "$rf")},
{"total",new BsonDocument("$sum", )},
{"totalpv",new BsonDocument("$sum", "$pv")},
{"totaluv",new BsonDocument("$sum", "$uv")},
{"totalui",new BsonDocument("$sum", "$ui")},
}; var project = new Dictionary<string, BsonValue>
{
{"day",},
{"pv",},
{"_id",},
{"total",new BsonDocument() {
new BsonElement("row","$total"),
new BsonElement("pv","$totalpv"),
new BsonElement("uv","$totaluv"),
new BsonElement("ui","$totalui"),
}},
{"area",},
{"uv",},
{"ui",},
{"nuv",},
{"ip",},
{"rfsite",},
}; var sitedayOptions = new List<BsonDocument>() {
new BsonDocument("$match",BsonDocument.Create(match)),
new BsonDocument("$group",BsonDocument.Create(group)),
new BsonDocument("$sort",new BsonDocument("_id",)),
new BsonDocument("$group",BsonDocument.Create(groupby)),
new BsonDocument("$project",BsonDocument.Create(project)),
}; var rel = sitesday.Aggregate(sitedayOptions);
//return rel.ToBsonDocument().ToString(); var result = rel.ResultDocuments.ElementAtOrDefault();
if (rel != null && rel.ResultDocuments.Count() > )
{
var rfbson= new BsonDocument() { };
result.ToBsonDocument().Add("rf", new BsonDocument() { });
foreach (var rfitem in result["rfsite"][].AsBsonArray)
{
foreach (var ritem in rfitem.ToBsonDocument())
{
if (result["rf"].ToBsonDocument().FirstOrDefault(e => e.Name.Equals(ritem.Name)) == null)
{
rfbson.Add(ritem.Name, ritem.Value.AsInt32);
}
else
{
rfbson[ritem.Name] = (rfbson[ritem.Name].AsInt32 + ritem.Value.AsInt32);
}
}
}
result["rf"] = rfbson;
}
return result.ToBsonDocument().ToString();
}

C#使用MapReduce实现对分片数据的分组的更多相关文章

  1. TableInputFormat分片及分片数据读取源码级分析

    我们在MapReduce中TextInputFormat分片和读取分片数据源码级分析 这篇中以TextInputFormat为例讲解了InputFormat的分片过程以及RecordReader读取分 ...

  2. MapReduce中TextInputFormat分片和读取分片数据源码级分析

    InputFormat主要用于描述输入数据的格式(我们只分析新API,即org.apache.hadoop.mapreduce.lib.input.InputFormat),提供以下两个功能: (1) ...

  3. shuffle机制和TextInputFormat分片和读取分片数据(九)

    shuffle机制 1:每个map有一个环形内存缓冲区,用于存储任务的输出.默认大小100MB(io.sort.mb属性),一旦达到阀值0.8(io.sort.spill.percent),一个后台线 ...

  4. 使用Hadoop的MapReduce与HDFS处理数据

    hadoop是一个分布式的基础架构,利用分布式实现高效的计算与储存,最核心的设计在于HDFS与MapReduce,HDFS提供了大量数据的存储,mapReduce提供了大量数据计算的实现,通过Java ...

  5. IOS第七天(3:UiTableView 模型和数据的分组的显示)

    *************UiTableView模型和数据的分组的显示 #import "HMViewController.h" #import "HMHero.h&qu ...

  6. Java将数据进行分组处理

    将传人的数据进行分组,使用map保存每组的数据. /** * 将取出的数据进行分组 * @param list * @return */ public Map<Integer,Object> ...

  7. 数据可视化之powerBI技巧(十七)在Power BI中对数据进行分组

    根据某一个维度的数据,进行分组统计,是很常见的做法,比如按年龄对客户进行分组,按考试成绩进行分组统计等,这篇文章介绍一下,在PowerBI中如何对数据进行分组. 在PowerQuery编辑器中分组 在 ...

  8. MapReduce分析明星微博数据

    互联网时代的到来,使得名人的形象变得更加鲜活,也拉近了明星和粉丝之间的距离.歌星.影星.体育明星.作家等名人通过互联网能够轻易实现和粉丝的互动,赚钱也变得前所未有的简单.同时,互联网的飞速发展本身也造 ...

  9. mapreduce导出MSSQL的数据到HDFS

    今天想通过一些数据,来测试一下我的<基于信息熵的无字典分词算法>这篇文章的正确性.就写了一下MapReduce程序从MSSQL SERVER2008数据库里取数据分析.程序发布到hadoo ...

随机推荐

  1. 本地ip变化,自定义IP地址

    1.打开网络和internet 设置 2.右键属性 3.修改

  2. django ----CBV中加装饰器

    CBV中加装饰器 from django import views from django.utils.decorators import method_decorator def login_aut ...

  3. Excel列名和列序号转换

    大家有没有留意过Excel表格中列名的规律呢?是这样的:A B C ... Y Z AA AB AC ... AY AZ BA BB BC ... BY BZ ... ZZ ... AAA ... 如 ...

  4. 实验吧—隐写术——WP之 我喜欢培根

    打开解题链接: 有一点点基础的同学大概都知道这是摩尔斯电码,那么我们对他进行解密: 解密后得到: MORSEnullISnullCOOLnullBUTnullBACONnullISnullCOOLER ...

  5. 转:《Javascript模块化编程》

    (一):模块的写法 转载至:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html (二):AMD规范 转载至:http://www ...

  6. debian 安装使用NTP

    编程之路刚刚开始,错误难免,希望大家能够指出. 领导要求,要4台机器时钟同步,上网查了查,主要看了看ptp和ntp,感觉ntp就够用,索性就直接上手ntp了. 以下内容纯属最基础的内容,只适合第一次接 ...

  7. 几种常见的微服务架构方案简述——ZeroC IceGrid、Spring Cloud、基于消息队列

    微服务架构是当前很热门的一个概念,它不是凭空产生的,是技术发展的必然结果.虽然微服务架构没有公认的技术标准和规范草案,但业界已经有一些很有影响力的开源微服务架构平台,架构师可以根据公司的技术实力并结合 ...

  8. MVC框架的理解(配置文件一次编写,所有的java代码都可以运行)

  9. access-control-allow-origin

    when use vastinspector to check our  vast response ,it  tiped : "no 'access-control-allow-origi ...

  10. DefinePlugin插件

    这个插件允许你创建全局常量用于编译时解析.如果设置mode:"production",webpack默认会设置"process.env.NODE_ENV": J ...