”。
db..distinct("zipcode",{"status" : 0})
3)group: 分组,注意它和aggregation中的“$group”有些类似,但不是一个操作,因为group无法在sharding环境中使用,所以mongodb建议使用“$group”进行替代,此处不再详解,请参见【group操作】
一、特性
1、Aggregation有几个核心的特性:
1)支持多种stages
2)可以将计算结果保存在collection中,在sharding环境中仍然适用,而且在output之前可以对结果数据进行“修剪”;当然可以将结果数据保存在内存(inline)并返回cursor,便于客户端访问结果数据。
3)同一种stage可以出现多次 ,这相对于mapreduce而言是个巨大的进步。(这种情况通常需要多个mapreduce才能完成)
4)stages中可以使用内置的多种计算操作、表达式,几乎可以覆盖绝大部分数据统计、分析的需求,所以用aggregation开发日常数据处理任务,是非常简单的事情。当然相对于mapreduce这种更加开放的计算模型(基于javascript语法和解析引擎),aggregation在计算复杂的数据任务时还不够灵活,但是书写mapreduce脚本也是一件复杂的事情。
2、局限性
无论如何,aggregation返回的计算结果,每条document的大小不得超过16M(mongodb中document的最大尺寸,此参数不可修改) ,在下文中我们会了解到$push、$addToSet等计算操作,有可能会导致此问题的发生。在一些计算方式中,可能最终结果只产出一条document,那么就更需要注意此问题。通常情况下,aggregation可以output任意多条documents,结果数据的总size是没有限制的,但是结果不能输出到sharding collection中 ,这与mapreduce是有区别的。
如果你从事过大数据计算、数据统计等相关工作,应该知道每个计算任务(job或task)都会使用独立的有限大小的内存空间,mongodb没有提供复杂的内存分配模型(任务调度算法),只是简单的限定每个stage最多使用100M内存,如果超过此值将终止计算并返回error;为了支持较大数据集合的处理,我们可以指定“allowDiskUse”参数将“溢出”的数据写入本地的临时文件中(临时的collection),这个参数我们通常需要设定为true。(参见上述示例)
3、优化
aggregation操作,简单而言就是将整个collection的数据全部input到pipeline中,经过多个stages计算之后,输出少量数据的过程。由mongodb引擎的特性决定,读取整个collection数据对磁盘和内存消耗都是非常巨大的,即使是在sharding环境中;那么尽可能的减少input数据量可以有效的提升处理的效率,对于有sort操作的,就需要更加谨慎,因为排序更加消耗内存和CPU。那么提高效率的手段之一,就是尽可能的使用索引(indexes),让$match和$sort尽可能的出现在pipeline的开端,$match使用索引可以更加高效的过滤input数据集进而不需要全表扫描,$sort使用索引可以避免额外的排序(因为索引本身就是有序的),索引只会在访问原始document时有效,如果是pipeline的中间数据,比如$group之后的$sort将无法使用到索引;当然索引的建立,是依据application中数据的访问模式而定,我们通常不会根据aggregation的需要而增加索引。
如果只需要对部分数据进行计算,那么可以将$match、$limit、$skip放置在pipeline的开端,那么handler只需要读取有效的、较少数量的documents;不恰当的做法,是将$limit、$skip放置在pipeline的末端,这意味着可能读取、处理更多的数据,产生更多的结果集,这意味着对性能的浪费。
4、sharded collection
上文已经提到sharding collection不支持group方法 (即db..group(),而非pipeline中的$group );但是它支持aggregation pipeline和mapreduce操作。当aggregation操作sharded collection时,pipeline将会被分成2部分:源数据过滤(filters),和后期处理(prost-processing) ;第一部分主要就是从collection中读取数据,或者根据索引过滤数据,位于pipeline开端的$match、$limit将会包含在内,mongos将会把aggregation操作发给特定的shards,如果$match中不包含sharding key,那么将会把操作发给所有的shards,并在每个shard上执行aggregation的第一部分的stages,此部分最大的特点就是不对数据进行计算,仅仅筛选并创建cursor;第二部分是后期处理部分,它将在primary shard上运行(概念参见【primary shard】),通常为$group、$unwind、$out、$project,其他stages也可以在第二部分,priamry合并其他shards上的cursor(迭代读取数据),读取数据并执行aggregation的第二部分的操作,然后将最终执行结果返回给mongos。(旧版中第二部分pipeline在mongos上执行);由此可见,尽可能早的过滤数据,可以有效降低primary的负载压力。我们可以在aggregate方法中指定“explain”参数,查看各个阶段执行的计划,其中cursor字段即为第一部分,其他的为第二部分,我们也能看出cursor分布在shards的情况。
db.orders.aggregate(
[
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
],
{
explain: true
}
)
其中limit、skip在各个shards上的分发原理,请参见【mongos部分】
3.2版本调整:mongodb为了提升sharding集群的整体性能,除了$out和$lookup需要在primary shard上运行外,其他的stages均可以并行的在符合匹配规则的shards执行,然后将各自的results数据转发给其中某个shard做最后的merge,这种方式有效了减轻了primary shard的负载压力;简单而言,3.2的pipleline处理模式基本没有改变,只是“第二部分”工作将从primary shard上转义到其中某个shard上。
二、Stages
Pipeline是有多个stages组成,每个stage提供不同的数据操作,stages在声明时是数组结构,具有有序性,当前stage的计算结果将作为下一个stage的输入 ,除$out之外,每种stages均可以在pipeline中出现多次 ,aggregate支持如下几种stages:
1、$project
与mongodb查询语句中的“projection”功能类似,对输入的document字段进行“取舍”,指定哪些字段将会包含(include)或者不包含(exclude)在输出中。
$project:{_id:0,name:{$concat:["$last", "," ,"$first"},"userid":1}
默认情况下“_id”字段一定被包含,除非显式指定“_id : 0”才能排除掉 ;“0”或者false表示“不包含”,“1”或者true表示包含,如果值是一个expression,则表示新增或者重置字段的值。比如上述文档,表示_id字段排除掉,“userid”字段包含,增加一个新字段“name”,其值为“last”和“first”两个字段值的拼接。
当需要增加一个字段,它的值确实是1、0、true或者false时,这就与$project语义有些冲突,为了确保值原样输出,那么就需要告知$project不要解析它们,这需要使用$literal操作符:
$project:{"sum":{$literal : 1}}
和document访问模式一样,$project也支持通过“.”路径访问内嵌文档:
$project:{_id:0,"friends.name":1}或者
$project:{_id:0,"firends":{"name":1}}
3.2+版本之后,$avg、$max、$min、$sum这四个“聚合函数”(原来只能在$group中使用)也可以在$project中使用了。
2、$match
根据query条件筛选文件,符合条件的文件将会传递给下一个stage。$match的语法和mongodb query语法一样,且$match中不能使用aggregate expression或者比较操作,只能使用query操作允许的操作符(参见Query操作) 。$match用于筛选数据,为了提高后续的数据处理效率,尽可能的将$match放于pipeline的前端以减少数据读取或者计算量;当然$match也可以放在$out之前用于控制数据输出量。如果$match放于pipeline的开始,还可以使用到indexes机制提高数据查询的性能。
$match:{"status":1}
3、$redact
根据字段所处的document结构的级别,对文档进行“修剪”,它通常和“判断语句if-else”结合使用即“$cond”。$redact可选值有3个:
1)$$DESCEND:包含当前document级别的所有fields。当前级别字段的内嵌文档将会被继续检测。
2)$$PRUNE:不包含当前文档或者内嵌文档级别的所有字段,不会继续检测此级别的其他字段,即使这些字段的内嵌文档持有相同的访问级别。
3)$$KEEP:包含当前文档或内嵌文档级别的所有字段,不再继续检测此级别的其他字段,即使这些字段的内嵌文档中持有不同的访问级别。
{
_id: 1,
tags: [ "G", "STLW" ],
year: 2014,
subsections: [
{
subtitle: "Section 1",
tags: [ "SI", "G" ],
},
{
subtitle: "Section 2",
tags: [ "STLW" ],
},
{
subtitle: "Section 3",
tags: [ "TK" ],
content: {
tags: [ "HCS" ]
}
}
]
}
那么对于语句:
$redact: {$cond: {
if: {
$gt: [ { $size: { $setIntersection: [ "$tags", ["STLW","G"] ] } }, 0 ] },
then: "$$DESCEND",
else: "$$PRUNE"
}
}
$setIntersection表示将2个数组的交集中不同元素的个数,$cond就是一个三元表达式,此例中表示“如果交集元素的个数大于0,则值为为$$DESCEND,否则为$$PRUNE”。对于此文档(ROOT级别)的最高级别的tags值为["G","STLW"],此级别值为$$DESCEND,即此tage同级别的其他字段将会包含;那么继续检测“subsections.tags”级别的所有文档(是个数组,则逐个检测),基本思路类似,如果此级别返回$$DECEND那么继续检测“subsections.tags.content.tags”是否符合访问规则,如果返回$$PRUNE,那么此tags所在的内嵌文档的所有字段将被排除,即使与此tags同级别的contents.tags符合访问规则。最终输出结果:
{
"_id" : 1,
"tags" : [ "G", "STLW" ],
"year" : 2014,
"subsections" : [
{
"subtitle" : "Section 1",
"tags" : [ "SI", "G" ],
"content" : "Section 1"
},
{
"subtitle" : "Section 2: Analysis",
"tags" : [ "STLW" ],
"content" : "Section 2"
}
]
}
4、$limit、$skip、$sort
同Query中的limit、skip、$sort限定符。如果$limit、$sort相邻出现,那么mongodb将会使用“TOP N”计算方式来处理数据,如果N较小这些数据可以在内存中排序完成,如果N很大(> 100M),则需要指定“allowDiskUse”为true,否则会发生错误。
5、$unwind
将指定的数组结构拆解成多条document,其中指定的Field必须是数组。3.2+版本之后,Field可以不是数组,此时将会把它当做只有一个item的数组处理。 比如文档:
{"_id" : 1,"item":"ABC1","sizes":["S","M","L"]}
执行$unwind:"$sizes"时输出结果为:
{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }
6、$out
必须为pipeline最后一个stage,将计算结果写入到指定的collection中,格式:$out : ,不支持sharded collection,也不支持capped collection 。如果指定的collection不存在,则直接创建。如果此collection已经存在,那么结果数据将原子性的替换旧的collection,即在结果数据写入时,不会改变原collection数据和索引,当数据写入完毕后原子性替换,,如果在写入出错时,原collection的数据不会有任何改变。
7、$group
分组,语义同SQL中的“group by”,语法:$group:{_id:,:{:},...}。“_id”字段是必须的,其值是group操作的key,可以为null或者计算表达式;可以增加其他自定义的字段,字段值可以为group支持的计算表达式(Expressions),$group首先将数据根据key进行分组,然后再对每个组执行如下的表达式计算:
1)$sum: 对每个group指定字段值进行累加计算。忽略非数字的值。
$group:{_id:"$productId","totalAmount":{$sum : "$quantity"}}
##在order表中,统计每个商品的销售总数量
2)$avg: 对每个group进行“平均值”,忽略非数字的值。
$group:{_id:"$categoryId","avgPrice":{$avg : "$price"}}
3)$first: 返回每个group的第一条数据,顺序有$sort决定,如果没有排序,默认为文档的自然存储顺序。
$sort:{categoryId : 1,price : 1},
$group:{_id:"categoryId","cheapest":{$first:"$price"}}
4)$last: 返回每个group的最后一条数据,顺序有$sort决定,如果没有排序,默认为文档的自然存储顺序。
5)$max、$min: 获取每个group中最大、最小值。
$sort:{categoryId:1}
$group:{_id:"categoryId","maxPrice":{$max:"$price"}}
##获取每个品类下,价格最高的商品
6)$push: 将指定的表达式的值添加到一个数组中,注意最终返回的document尺寸不要超过16M。
$group:{_id:"author","bookIds":{$push:"$bookId"}}
##获取每个作者的图书ID的列表
7)$addToSet: 将表达式的值添加到一个集合中(无重复值),注意最终分那会的document尺寸不要超过16M。
$group:{_id:"categoryId","shopIds":{$addToSet:"$shopId"}}
##获取每个品类下,不同商铺的ID
上述7个操作符只能在$group中使用 ,$group通常用于获取某一维度不同的值、计算总和、分类数据,是aggregation操作中最重要的stage;如果将group的功能转换成mapreduce可能需要书写大量的代码。$group的key可以为null或者一个常量值,用于计算全局的数据,比如统计所有“商品的库存总价值”:
$group:null,"total":{$sum:{$multiply:["$price","$quantity"]}}
8)$geoNear: 用于地理位置数据分析,参见【geoNear】
9)$sample:
3.2+版本中新增 ,类似于大数据中的“数据采样”方式,从input中随机选择N条documents,语法“{$sample: {size: }}”。如果N大于collection中总数据的5%,那么$sample将会执行collection扫描、sort,然后选择top N条文档;如果N小于5%,对于wiredTiger而言则会遍历collection并使用“伪随机”的方式选取N条文档,对于MMAPv1引擎则在_id索引上随机选取N条文档。(本文没有测试$sample)
10)$lookup
3.2+版本新增 ,“left outer join”功能;从事过大数据开发的人都知道,如果仅仅基于mapreducer计算模式,实现跨文件“join”还是一件比较复杂的事情;mongodb提供了$lookup以支持简单的join,以当前collection作为主表(左端),将另一个non-sharded collection作为辅表参与join。语法:
{
$lookup:
{
from: <参与join的辅表>,
localField: <参与join匹配的本表字段>
foreignField: <参与join的辅表字段>
as: <将辅表数据输出到此字段中>
}
}
其中from表示一个参与join的辅表,这个表不能是sharding collection;localField和foreignField就是参与join的key,如果documents不存在上述field,那么将以null参与匹配;“as”指定一个输出字段,将辅表匹配成功的documents添加到此“字段”中,作为结果输出。
##比如主表为orders,数据结构为:
{_id:1,"product_id":1000,"price":30.0}
##辅表为products,数据结果为:
{_id:1,"id":1000,"name":"mongodb reference"}
{
$lookup: {
from:"products",
localField:"product_id",
foreignField:"id",
as:"products"
}
}
执行结果可能类似于:
{
_id:1,
"product_id":1000,
"price":32.0,
"products":[
{_id:1,id:1000,"name":"mongodb reference"}
]
}
三、Expressions(表达式)
在$group中我们已经了解到了几个expressions,此外aggregation还支持多种其他类型的表达式,它们为计算过程提供了很大的便利性。$match只能使用query支持的表达式,$group中特定的几个表达式只能在$group中使用,对于其他的stage均可以使用下文中介绍的表达式。 【参见表达式】
表达式中可以使用“field path”(字段路径)来访问输入文档的字段值,字段路径有“$”和字段名称构成,即“$”,比如:$userid表示访问useid字段值,支持内嵌文档的访问,比如$user.name。有一个特殊的字段路径,即$$ROOT或者$$CURRENT,表示当前文档,$$ROOT.userid其实和$userid一样,我们通常在使用字段路径时忽略$$ROOT。$$ROOT、$$CURRENT和上文提到的$$DESCEND、$$PRUNE、$$KEEP一样,同属系统变量。不过通常我们还需要在aggregate中声明自定义的变量。
1、自定义变量
1)$let
指定临时变量,并返回变量计算的结果。$let包含2个字段:vars和in,其中vars用该声明临时变量,in用来计算,其中vars中的变量只能在in中使用,其生命周期也只在当前$let中有效;为了避免与“字段路径”的访问模式混淆,在in中访问vars中的变量需要使用$$前缀。示例:
$project:{
totalAmount :{
$let {
vars : {
total : {$multiply : {$price,$quantity}},
in: {$subtract : {'$$total','$discounted'}}
}
}
}
在$let中声明一个变量total,值为价格与数量乘积,最终totalAmount的值为“总价 - 折扣”。
2)$map
对array数组元素进行迭代,并返回一个新的数组。类似一个foreach过程,语法结构如下:
$map : {input:,as:- ,in:
}
它有三个字段,input表示需要计算的数组,as表示当前数组元素的别名,in可以使用当前元素的别名进行计算;示例如下:
##原始数据
{_id : 1, "numbers" : [2,5,8]}
{_id : 2, "numbers" : [0,1,3]}
##aggregation
$project : {
"numbers" : {
$map : {input : "$numbers",as:"item",in:{$add : {'$item',2}}}
}
}
##result
{_id : 1, "numbers" : [4,7,9]}
{_id : 2, "numbers" : [2,3,5]}
2、$literal(字面值)
或许大家都比较熟悉这个概念,即$literal的值仅作字符串处理,原样输出,不进行表达式解析和计算,这类似于XML结构中的CDATA。比如:
$literal : {$add: [2,3]} 最终输出"$add:[2,3]"
$literal : "$name" 最终输出"$name"
##----示例----
##原始文档
{_id:1,"product":"book1","price":"$10"}
{_id:1,"product":"book2","price":"45.01"}
##aggregation
{$project:
{costByDollar:{
$eq : [
{$literal : "$"},{$substr:["$price",0,1]}
]
}
}
##输出结果
{_id:1,"costByDollar":true}
{_id:1,"costByDollar":false}
3、Boolean表达式
表达式返回true或者false,目前支持三种操作$and、$or、$not;语义基本与query中相同操作符一致。具体参见【Boolean】
4、比较表达式(Comparison)
语义基本同query,只是语法不同,它们需要返回true、false,比如:$eq、$gt等等。参见【Comparison】
5、集合操作(Set)
对于多个Arrays进行比较操作:
1)$setEquals:如果输入的两个或者多个Arrays中都持有相同的Set(不同值的列表)则返回true,否则返回false。
2)$setIntersection:返回输入的多个Arrays的交集。
3)$setUnion:返回并集。
5)$setDifference:返回差集,即在第一个Set中存在,但在第二个Set中不存在的数组元素。只接收2个数组参数。
6)$setIsSubset:如果第一个Set为第二个Set的子集(包括完全相同)则返回true,否则返回false。
7)$anyElementsTrue:如果此Set中有任何一个值为true,则返回true,否则返回false。只接收一个Array参数。
8)$allElementsTrue:只有当所有的元素都为true时,才返回true。只接收一个Array参数。
6、数学计算
对数字类型的字段值进行计算,比如$add(+),$subtract(-),$multiply(*),$divide(/),$mod(%),3.2版本新增计算表达式;语法都一样,例如:
$project : {
totalAmount : {$multiply: {"$price","$qunatity"}}
}
7、字符串操作
对字符串进行操作,非常简便有用的方法:
1)$concat: 拼接字符串,此操作可以接收多个参数列表。
$concat:["$lastname",",","$firstname"]
2)$substr: 截取字符串,语法:$substr : [ ,,],其中start默认起始为0。
3)$toLower、$toUper: 大小写转换
4)$strcasecmp: 不分大小写,进行字符串比较,如果2个字符串一样,则返回0;如果第一个字符串比第二个“大”(字典顺序),则返回1,否则返回false。
8、$size: 计算数组的元素个数,语法:$size : ;3.2版本新增数组表达式
9、日期计算
对Date或者timestamp进行计算,比如获取时间的月份、时间戳等等。简单列举如下:
$dayOfYear:当前日期是此年的第几天,0~366(闰年);$dayOfMonth:当前日期是本月的第几天,0~31;$dayOfWeek:当前日期是本周的第几天,1~7,1表示周日,7表示周六;$year:返回当前日期的年份,比如2014。$month:返回当前日期的月份。$week:返回当前日期为当年的第几周,0~53周。$hour、$minute、$second、$millisecond表示获取当前日期的时、分、秒、毫秒部分。
$dateToString:日期的格式转换,这个比较常用,语法格式:$dataToString : {format:,date:"$date"}。格式占位符如下:
%Y: 年份,4个数字,比如2014;%m: 月份,2个数字,01~12;%d: 日期,2个数字,01~31;%H: 小时,2个数字,00~23;%M: 分钟,00~59;%S: 秒,00~59;%L: 毫秒,000~999;%j: 当前day为年的第几天,001~366;%U: 当前日期所在年的第几周,00~53;%w: day是当前周的第几天,1~7。
$project : {
"dateAsString":{$dateToString:{format:"%Y-%m-%d %H:%M:%S",date:"$date"}}
}
10、条件表达式
1)$cond
上文中我们已经看到相关示例,它的作用等同于一个“三元表达式”,语法:$cond:{if : , then : ,else : }。
2)$ifNull
判定指定表达式是否为null,比如字段不存在(undefined)、值为null。语法:$ifNull: [,],如果expression的值为null则返回“return-value”。
四、示例
通过上文,我们基本了解了aggretation的原理和使用技巧,对于复杂的数据计算通常需要多次计算才能产出结果。此外还需要强调一点,良好的数据结构和数据存储模型,对数据分析和统计具有非常大的帮助 ,所以我们希望大家在数据分析之前,和appliation约定数据的模型,如果数据模型相差甚远,那么需要进行一次(或者增量的)清洗数据,并转存到特定的数据仓库中(比如mongodb,hive等)。
因为aggregate和mapreduce每次任务只能操作一个collection,数据数据来自多个collection,那么就需要多次分析,将分析结果统一写入一个result collection中,然后在对result进行最终的计算。
数据校对是个非常棘手的问题,通常可以采用“取样法”来测试,比如限定一定范围(或者随机)对整体数据取样1/10,然后对这个小数据集先运行数据统计脚本,查看结果是否有异动,对于异常情况适度调整算法。
接下来我们使用aggregate操作完成如下数据统计指标:
1)横向维度: 统计当前月份之前的6个月新用户在当月的留存;比如现在为9月份,统计出3~8月份注册的用户,在9月份的留存情况。
2)纵向维度: 分平台,分别统计“android”、“ios”、“pc”三个平台在横向维度的数据。
期望数据结果:
-------------------------------------------------------------
| 平台\月份 | 1 | 2 | 3 | 4 | 5 | 6 |
-------------------------------------------------------------
| android | 100 | 80 | 100 | 150 | 160 | 200 |
-------------------------------------------------------------
| ios | 100 | 80 | 100 | 150 | 160 | 200 |
-------------------------------------------------------------
| pc | 100 | 80 | 100 | 150 | 160 | 200 |
-------------------------------------------------------------
我们假定有个collection为user,当用户注册时新建一条记录,created表示用户注册的时间,modfied表示用户最后登录的时间;userid上创建唯一索引,created、modified创建了组合索引,原始数据格式:
{_id : 1,userid:"10010","platform":"android","created":{"$date":1448805204482},"modified":{"$date":1448805204482}
aggregate语句:
db.user.aggregate([
{ "$match" : {
"created" : {
"$gte" : { "$date" : 1430379347719 }, "$lt" : { "$date" : 1446307200000 } },
"modified" : { "$gte" : { "$date" : 1446190547719 } }
}
},
{ "$group" : {
"_id" : { "month" : { "$month" : "$created" },
"platform" : "$platform" },
"total" : { "$sum" : 1 }
}
},
{ "$project" : {
"platform" : "$_id.platform",
"total" : 1,
"month" : "$_id.month",
"_id" : 0
}
},
{ "$sort" : { "platform" : 1, "month" : 1 } },
{ "$group" : {
"_id" : "$platform",
"result" : { "$push" : { "month" : "$month", "total" : "$total" } }
}
},
{ "$match" : {
"created" : { "$gte" : { "$date" : 1430379347719 }, "$lt" : { "$date" : 1446307200000 } },
"modified" : { "$gte" : { "$date" : 1446190547719 } }
}
},
{ "$group" : {
"_id" : { "month" : { "$month" : "$created" }, "platform" : "$platform" },
"total" : { "$sum" : 1 }
}
},
{ "$project" : {
"platform" : "$_id.platform",
"total" : 1,
"month" : "$_id.month",
"_id" : 0
}
},
{ "$sort" : { "platform" : 1, "month" : 1 } }
]
}
JAVA程序实例:
MongoCollection collection = db.getCollection("user");
Date now = new Date();//11月30日
List pipeline = new ArrayList();
Document filter = new Document();
//过滤:
//1)注册时间在6各月之前,不包括当月;
//2)最后登陆时间在当月
filter.put("created",
new Document("$gte",DateUtils.addMonths(now, -7)).append("$lt", DateUtils.truncate(now, Calendar.MONTH)));
filter.put("modified",new Document("$gte",DateUtils.addMonths(now, -1)));
Document match = new Document("$match",filter);
pipeline.add(match);
Document group = new Document();
//第一次group,将“月份”和“平台”作为复合key
group.put("$group", new Document("_id", new Document("month", new Document("$month", "$created")).append("platform", "$platform"))
.append("total", new Document("$sum", 1)));
pipeline.add(group);
//重命名字段名
Document project = new Document("$project",new Document("platform","$_id.platform")
.append("total",1).append("month","$_id.month").append("_id",0));
pipeline.add(project);
//按照平台和月份排序,确保,同一个平台的数据,是按照月份排序的,因为接下来要使用$push
Document sort = new Document("$sort",new Document("platform",1).append("month", 1));
pipeline.add(sort);
//第二次group,将上述输出数据,转换成根据平台为维度的inline方式。便于页面展示。
Document finalGroup = new Document("$group",new Document("_id","$platform")
.append("result", new Document("$push", new Document("month", "$month").append("total", "$total"))));
pipeline.add(finalGroup);
//pipeline.add(new Document("$out","_" + DateFormatUtils.format(now,"yyyyMMdd")));
MongoCursor cursor = collection.aggregate(pipeline).allowDiskUse(true).iterator();
while (cursor.hasNext()) {
Document item = cursor.next();
System.out.println(item.toJson());
}
cursor.close();
输出结果示例:
{
"_id": "pc",
"result": [
{
"month": 5,
"total": 2736
},
{
"month": 6,
"total": 2877
},
{
"month": 7,
"total": 2718
},
{
"month": 8,
"total": 2791
},
{
"month": 9,
"total": 2887
},
{
"month": 10,
"total": 2800
}
]
}
{
"_id": "android",
"result": [
{
"month": 5,
"total": 2742
},
{
"month": 6,
"total": 2850
},
{
"month": 7,
"total": 2782
},
{
"month": 8,
"total": 2752
},
{
"month": 9,
"total": 2740
},
{
"month": 10,
"total": 2941
}
]
}
非常有趣的是,aggreate可以支持2个group、甚至更多个group操作,这大大减少了数据分析的开发难度,如果使用mapreduce可能需要开发多个脚本且运行多次。在技术日新月异的今天,基于大数据平台的数据计算技术不断涌现,出现大量了“SQL-LIKE Engineer”,它们可以将SQL语句转换成适用于NOSQL平台的操作,比如将SQL语句转换成Mongodb的aggreation或者mapreduce(内部或将数据转存到hadoop上进行mapreduce),这样又进一步的提升了开发效率,我们稍后介绍Apache Drill:mongodb平台上的SQL-Like引擎。
你可能感兴趣的:(Mongodb中Aggregation特性)
《极简思维》第三部分
小洋苏兮
整理你的人际关系如何改善人际关系?摘录:因为人际关系问题是人们生活中不快乐的主要原因。感想:感觉这个说的挺对,之前我总是埋头学习,不管舍友不管自己的合作伙伴的一些事情,但实际上,这学期关注了之后好多了摘录:“亲密关系与社交会让你健康而快乐。这是基础。太过于关注成就或不太关心人际关系的人都不怎么快乐。基本上来说,人类就是建立在人脉关系上的。”感想:但是如果有时想的太多就不太好,要以一个开放的心态跟别
C++ 计数排序、归并排序、快速排序
每天搬一点点砖
c++ 数据结构 算法
计数排序:是一种基于哈希的排序算法。他的基本思想是通过统计每个元素的出现次数,然后根据统计结果将元素依次放入排序后的序列中。这种排序算法适用于范围较小的情况,例如整数范围在0到k之间计数排序步骤:1初始化一个长度为最大元素值加1的计数数组,所有元素初始化为02遍历原始数组,将每个元素值作为索引,在计数数组中对应位置加13将数组清空4遍历计数器数组,按照数组中的元素个数放回到元数组中计数排序的优点和
Git 与 GitHub 的对比与使用指南
一念&
其它 git github
Git与GitHub的对比与使用指南在软件开发中,Git和GitHub是两个密切相关但本质不同的工具。下面我将逐步解释它们的定义、区别、核心概念以及如何协同使用,确保内容真实可靠,基于广泛的技术实践。1.什么是Git?Git是一个分布式版本控制系统,由LinusTorvalds于2005年创建。它的核心功能是跟踪代码文件的变化,帮助开发者管理项目历史记录、协作和回滚错误。Git是开源的,可以在本地
Linux系统配置(应用程序)
1风天云月
Linux linux 应用程序 编译安装 rpm http
目录前言一、应用程序概述1、命令与程序的关系2、程序的组成3、软件包封装类型二、RPM1、RPM概述2、RPM用法三、编译安装1、解包2、配置3、编译4、安装5、启用httpd服务结语前言在Linux中的应用程序被视为将软件包安装到系统中后产生的各种文档,其中包括可执行文件、配置文件、用户手册等内容,这些文档被组织为一个有机的整体,为用户提供特定的功能,因此对于“安装软件包”与“安装应用程序”这两
关于流媒体播放器EasyPlayer和EasyPlayerPro的介绍以及其区别
EasyDarwin
EasyDarwin 音视频 ffmpeg 人工智能 大数据 ar
EasyPlayer是一款流媒体播放器系列项目,它支持多种流媒体协议的播放,包括但不限于RTSP、RTMP、HTTP、HLS、UDP、RTP、File等。除此之外,EasyPlayer还支持本地文件播放和多种功能特性,包括本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等。EasyPlayer核心基于ffmpeg,稳定、高效、可靠、可控。随着多年的不断发展和迭代,EasyPlayer基于成功的实践
Flowable 实战落地核心:选型决策与坑点破解
练习时长两年半的程序员小胡
Flowable 流程引擎实战指南 低代码 BPMN 流程引擎 flowable 后端 java
在企业级流程引擎的落地过程中,选型的准确性和坑点的预见性直接决定项目成败。本文聚焦Flowable实战中最关键的“选型决策”与“常见坑点”,结合真实项目经验,提供可落地的解决方案。一、流程引擎选型:从业务本质出发1.1选型的三大核心维度企业在选择流程引擎时,需避免陷入“技术崇拜”,应回归业务本质。评估Flowable是否适用,可从三个维度判断:业务复杂度若流程涉及动态审批链(如按金额自动升级审批)
Flowable 高级扩展:自定义元素与性能优化实战
练习时长两年半的程序员小胡
Flowable 流程引擎实战指南 流程图 flowable BPMN 流程引擎 java
在前五篇文章中,我们从基础概念、流程设计、API实战、SpringBoot集成,到外部系统协同,逐步构建了Flowable的应用体系。但企业级复杂场景中,原生功能往往难以满足定制化需求——比如需要特殊的审批规则网关、与决策引擎联动实现动态路由,或是在高并发场景下优化流程引擎性能。本文将聚焦Flowable的高级扩展能力,详解如何自定义流程元素、集成规则引擎,并掌握大型系统中的性能调优策略。一、自定
互信息:理论框架、跨学科应用与前沿进展
大千AI助手
人工智能 Python # OTHER 人工智能 深度学习 算法 互信息 香农 通信 随机变量
1.起源与核心定义互信息(MutualInformation,MI)由克劳德·香农(ClaudeShannon)在1948年开创性论文《AMathematicalTheoryofCommunication》中首次提出,该论文奠定了现代信息论的基础。互信息用于量化两个随机变量之间的统计依赖关系,定义为:若已知一个随机变量的取值,能为另一个随机变量提供的信息量。数学上,对于离散随机变量XXX和YYY,
《实际生活是我们的指南针》——教育中寻找曙光
托克托126何芳
陶行知先生的文章相对《致青年教师》比较难理解,但是他热爱学生,在书中处处能感受到。在《实际生活是我们的指南针》文中他说道:“我虽觉得我有好多地方可以帮助诸位,但指志针确是有些不敢当。我和诸位同是在乡村里摸路的人。我们的真正指南针只是实际生活。”这些话不仅使人感到他非常谦虛,既不夸大自己的作用也不轻视自己的作用。图片发自App我们的真正指南针只是实际生活。实际生活向我们供给无穷的问题,要求不断的解决
车载刷写架构 --- 整车刷写中为何增加了ECU 队列刷写策略?
汽车电子实验室
电子电器架构——刷写方案 车载电子电气架构 架构 开发语言 车载诊断进阶篇 汽车中央控制单元HPC软件架构 关于网关转发性能引起的思考
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师:周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧!旧人不知我近况,新人不知我过往,近况不该旧人知,过往不与新人讲。纵你阅人何其多,再无一人恰似我。时间不知不觉中,来到新的一年。2025开始新的忙碌。成年人的我也不知道去哪里渡
在线人数统计业务设计(场景八股文)
业务问题在当经的网站中,在线人数的实时统计已经是一个必不可少的模块了,并且该统计功能最好能够按不同的时间间隔做的统计,现在需要你设计一个在线人数统计的模块,你应该怎么进行设计的呢?背景一个网校下会有多个学员。目前平台大概有十个,平台对应的网校大概五十几个,平均一个网校会有5w个用户,预计总人数为200w,最该学员的在线人数在10w左右。设计思路最开始的时候,想到的就是使用mysql直接实现,但是明
JAVA接口机结构解析
秃狼
SpringBoot 八股文 Java java 学习
什么是接口机在Java项目中,接口机通常指用于与外部系统进行数据交互的中间层,负责处理请求和响应的转换、协议适配、数据格式转换等任务。接口机的结构我们的接口机的结构分为两个大部分,外部接口机和内部接口机,在业务的调度上也是通过mq来实现的,只要的目的就是为了解耦合和做差异化。在接口机中主要的方法就是定时任务,消息的发送和消费,其他平台调用接口机只能提供外部接口机的方法进行调用,外部接口机可以提供消
Aop +反射 实现方法版本动态切换
需求分析在做技术选型的时候一直存在着两个声音,mongo作为数据库比较mysql好,mysql做为该数据比mongo好。当然不同数据库都有有着自己的优势,我们在做技术选型的时候无非就是做到对数据库的扬长避短。mysql最大的优势就是支持事务,事务的五大特性保证的业务可靠性,随之而来的就是事务会产生的问题:脏读、幻读、不可重复度,当然我们也会使用不同的隔离级别来解决。(最典型的业务问题:银行存取钱)
读书打卡《别想太多啦》
chenchen_68ed
第一,世间之事,不去尝试永远不知道其中的奥秘,在尝试中有失败是必然的。如果担心失败,那什么都学不会。第二,经历的失败越多,越会对失败者抱有宽容的态度,“原来如此,我也经历过类似的失败啦,那只是暂时的”。经历越多失败的长者,越能包容别人,这也就是所谓的“越年长越宽容”。成熟的人,就是在众多失败经历中不断学习,并接纳别人的失败。对于他人的小小过失不吹毛求疵,自己的心态会更加平和。在不断失败中学习,让自
模拟退火(SA):如何“故意走错路”,才能找到最优解?
小瑞瑞acd
小瑞瑞学数模 模拟退火算法 python 启发式算法 算法
模拟退火(SA):如何“故意走错路”,才能找到最优解?图示模拟退火算法如何通过接受较差解(橙色虚线标注)从局部最优(绿色点)逃逸,最终找到全局最优解(紫色点),展示其跳出局部极小值的能力。大家好,我是小瑞瑞!欢迎回到我的专栏!想象一下,你站在一座连绵不绝的山脉中,目标是找到海拔最低的那个山谷。你手上只有一个高度计,视野被浓雾笼罩,只能看清脚下的一小片区域。如果你是一个“贪心”的登山者,你的策略会非
京东家电年销售额是去年的1300%,主要来自于他....
Shanshan小课堂
经过大半个月角逐纠缠,时间终于来到6月18日,618全球年中购物节迎来最高潮。作为国内最大的家电零售平台,京东家电从18日0点开始,便开启了飞速狂奔的模式,仅8分钟销售额就突破20亿元!展现出强劲的增长势头与家电主场的王者霸气的同时,也让各家电品牌实现了爆发式增长,美的、海尔、格力、奥克斯均在3分钟内突破1亿元大关。在今年的618中,除了消费者已经熟悉的网购形式外,线上线下联动的融合模式、社交电商
编程算法:技术创新的引擎与业务增长的核心驱动力
在数字经济时代,算法已成为推动技术创新与业务增长的隐形引擎。从存内计算突破冯·诺依曼瓶颈,到动态规划优化万亿级金融交易,编程算法正在重塑产业竞争格局。一、存内计算:突破冯·诺依曼瓶颈的算法革命1.1存内计算的基本原理传统计算架构中90%的能耗消耗在数据搬运上。存内计算(Processing-in-Memory)通过直接在存储单元执行计算,实现能效10-100倍提升:#传统计算vs存内计算能耗模型i
二十四节气组诗 谷雨
离陌_6639
图片来源网络,若侵犯了你的权益,请联系我删除6.谷雨文/离陌背上行囊背上如行囊的我从此任行程马不停蹄今天家乡的田野春雨快马加鞭播下希望的种子观音不语目送着我和夏天一道在观音山出关图片来源网络,若侵犯了你的权益,请联系我删除你好啊,我是离陌,已然在懵懂中走过了16年的岁月,为了珍惜当下的每一秒,所以立志做一名终身学习者。文学对于我来说是一种信仰,诗歌是我的生命。人生之道,四通八达,即入文学,自当持之
基于redis的Zset实现作者的轻量级排名
周童學
Java redis 数据库 缓存
基于redis的Zset实现轻量级作者排名系统在今天的技术架构中,Redis是一种广泛使用的内存数据存储系统,尤其在需要高效检索和排序的场景中表现优异。在本篇博客中,我们将深入探讨如何使用Redis的有序集合(ZSet)构建一个高效的笔记排行榜系统,并提供相关代码示例和详细的解析。1.功能背景与需求假设我们有一个笔记分享平台,用户可以发布各种笔记,系统需要根据用户发布的笔记数量来生成一个实时更新的
【项目实战】 容错机制与故障恢复:保障系统连续性的核心体系
本本本添哥
004 - 研效与DevOps运维工具链 002 - 进阶开发能力 分布式
在分布式系统中,硬件故障、网络波动、软件异常等问题难以避免。容错机制与故障恢复的核心目标是:通过主动检测故障、自动隔离风险、快速转移负载、重建数据一致性,最大限度减少故障对业务的影响,保障系统“持续可用”与“数据不丢失”。以下从核心机制、实现方式、典型案例等维度展开说明。一、故障检测:及时发现异常节点故障检测是容错的第一步,需通过多维度手段实时感知系统组件状态,确保故障被快速识别。1.健康检查与心
【 焦点咨询的“无为”】邹庆会,持续分享第690天,2020年1月23日
邹庆会
焦点课堂上,刘老师强调,焦点咨询师要“无为”,当时我就很困惑:我们“无为”,我们什么都不做,那来访者找我们做什么呢?那我们又怎么样来引领来访者呢?又怎么样让来访者在咨询当中有更多的收获呢?带着这个困惑,我逐渐在咨询中,包括在陪伴儿子的过程中,试着慢慢地放下期待、忘掉技术,寻找“无为”的感觉,寻找“无为”的痕迹,以及“无为”之后的一些效果的呈现。也慢慢的悟出一些自己的感受和体会。就像《道德经》中所说
Java并发核心:线程池使用技巧与最佳实践! | 多线程篇(五)
bug菌¹
Java实战(进阶版) java Java零基础入门 Java并发 线程池 多线程篇
本文收录于「Java进阶实战」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!环境说明:Windows10+IntelliJIDEA2021.3.2+Jdk1.8本文目录前言摘要正文何为线程池?为什么需要线程池?线程池的好处线程池使用场景如何创建线程池?线程池的常见配置源码解析案例分享案例代码演示案例运行
Java 队列
tryxr
java 开发语言 队列
队列一般用什么哪种结构实现队列的特性数据入队列时一定是从尾部插入吗数据出队列时一定是从头部删除吗队列的基本运算有什么队列支持随机访问吗队列的英文表示什么是队列队列从哪进、从哪出队列的进出顺序队列是用哪种结构实现的Queue和Deque有什么区别Queue接口的方法Queue中的add与offer的区别offer、poll、peek的模拟实现如何利用链表实现队列如何利用顺序表实现队列什么叫做双端队列
分支和循环(下)
tryxr
服务器 运维
写⼀个猜数字游戏游戏要求:1.电脑⾃动⽣成1~100的随机数2.玩家猜数字,猜数字的过程中,根据猜测数据的⼤⼩给出⼤了或⼩了的反馈,直到猜对,游戏结束1.随机数生成要想完成猜数字游戏,⾸先得产⽣随机数,那怎么产⽣随机数呢?randC语⾔提供了⼀个函数叫rand,这函数是可以⽣成随机数的,函数原型如下所⽰:intrand(void);rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_
四百八十九章. 春晓客栈鲁易寒
巨木擎天
邓林他们在打量别人的时候,而别人,自然也是在打量他们了。邓林就看见在这大堂里,散散啦啦的有四个人在,其中两个,只是僵直站立,眼眶中燃烧着橙色骨火的骷髅,而另外两个坐着的,才是眼眶中点燃黄色魂火的骨族人。这两个骨族人中的一个,在邓林他们刚一进来的时候,就把注意力都放在了伊莲娜娜的身上,似乎在确认着什么,当看到伊莲娜娜冲着自己点了点头以后,他有些激动的走过来几步,口中说道:“真的是伊莲娜娜公主殿下?您
STM32入门之TIM基本定时器
嵌入式白话
STM32入门学习 stm32 嵌入式硬件 单片机
一、定时器简介定时器是嵌入式系统中的关键外设之一,它可以用于生成精确的延时、周期性中断、PWM波形生成等功能。在STM32F1系列单片机中,定时器不仅能为系统提供精确的时钟,还支持外部事件的捕获以及信号输出。对于定时器的功能,我们可以通过一个生活中非常常见的例子来形象地描述:微波炉的定时器。想象你正在使用微波炉加热食物。在微波炉里,定时器的作用就是帮助你控制食物加热的时间。当你设置了加热时间后,定
5G-RAN与语义通信RAN
一去不复返的通信er
智简网络&语义通信 5G 人工智能 语义通信
1️⃣RAN协议栈与TCP/IP五层协议栈的对应关系a.物理层(TCP/IP)↔PHY(RAN)对应关系:5GNRRAN的物理层直接对应TCP/IP的物理层。功能对比:TCP/IP物理层:负责比特流的物理传输,如通过电缆、光纤或无线介质传输信号。RAN物理层:处理无线信号的调制、编码、信道估计和传输(如OFDM、LDPC编码)。在5GNR中,物理层负责将数据映射到无线信道(如PDSCH、PUSCH
常规笔记本和加固笔记本的区别
luchengtech
电脑 三防笔记本 加固计算机 加固笔记本
在现代科技产品中,笔记本电脑因其便携性和功能性被广泛应用。根据使用场景和需求的不同,笔记本可分为常规笔记本和加固笔记本,二者在多个方面存在显著区别。适用场景是区分二者的重要标志。常规笔记本主要面向普通消费者和办公人群,适用于家庭娱乐、日常办公、学生学习等相对稳定的室内环境。比如,人们在家用它追剧、处理文档,学生在教室用它完成作业。而加固笔记本则专为特殊行业设计,像军事、野外勘探、工业制造、交通运输
JVM 内存分配与回收策略:从对象创建到内存释放的全流程
在JVM的运行机制中,内存分配与回收策略是连接对象生命周期与垃圾收集器的桥梁。它决定了对象在堆内存中的创建位置、存活过程中的区域迁移,以及最终被回收的时机。合理的内存分配策略能减少GC频率、降低停顿时间,是优化Java应用性能的核心环节。本文将系统解析JVM的内存分配规则、对象晋升机制,以及实战中的内存优化技巧。一、对象优先在Eden区分配:新生代的“临时缓冲区”大多数情况下,Java对象在新生代
2019做重要的事,让遗憾减少
Sandy黄珊丹
岁末年初,又到了回顾和展望的时间。回顾2018,你有哪些事情没有去做或者没有做到而感到遗憾的呢?2019年我们要怎么做,可以减少遗憾呢?回想自己在2017年以前,一直处在忙碌的家庭和事业中,忙碌让我感到安全,稍微停下脚步都感到是一种罪过,每一件事似乎都很重要。直到2017春节后,因为对未来彷徨和焦虑,让我严重失眠,家庭关系恶化,都让心疲惫无法进入工作状态,不得不寻找解决的的办法。在2017年5月份
mongodb3.03开启认证
21jhf
mongodb
下载了最新mongodb3.03版本,当使用--auth 参数命令行开启mongodb用户认证时遇到很多问题,现总结如下:
(百度上搜到的基本都是老版本的,看到db.addUser的就是,请忽略)
Windows下我做了一个bat文件,用来启动mongodb,命令行如下:
mongod --dbpath db\data --port 27017 --directoryperdb --logp
【Spark103】Task not serializable
bit1129
Serializable
Task not serializable是Spark开发过程最令人头疼的问题之一,这里记录下出现这个问题的两个实例,一个是自己遇到的,另一个是stackoverflow上看到。等有时间了再仔细探究出现Task not serialiazable的各种原因以及出现问题后如何快速定位问题的所在,至少目前阶段碰到此类问题,没有什么章法
1.
package spark.exampl
你所熟知的 LRU(最近最少使用)
dalan_123
java
关于LRU这个名词在很多地方或听说,或使用,接下来看下lru缓存回收的实现
1、大体的想法
a、查询出最近最晚使用的项
b、给最近的使用的项做标记
通过使用链表就可以完成这两个操作,关于最近最少使用的项只需要返回链表的尾部;标记最近使用的项,只需要将该项移除并放置到头部,那么难点就出现 你如何能够快速在链表定位对应的该项?
这时候多
Javascript 跨域
周凡杨
JavaScript jsonp 跨域 cross-domain
 
linux下安装apache服务器
g21121
apache
安装apache
下载windows版本apache,下载地址:http://httpd.apache.org/download.cgi
1.windows下安装apache
Windows下安装apache比较简单,注意选择路径和端口即可,这里就不再赘述了。 2.linux下安装apache:
下载之后上传到linux的相关目录,这里指定为/home/apach
FineReport的JS编辑框和URL地址栏语法简介
老A不折腾
finereport web报表 报表软件 语法总结
JS编辑框:
1.FineReport的js。
作为一款BS产品,browser端的JavaScript是必不可少的。
FineReport中的js是已经调用了finereport.js的。
大家知道,预览报表时,报表servlet会将cpt模板转为html,在这个html的head头部中会引入FineReport的js,这个finereport.js中包含了许多内置的fun
根据STATUS信息对MySQL进行优化
墙头上一根草
status
mysql 查看当前正在执行的操作,即正在执行的sql语句的方法为:
show processlist 命令
mysql> show global status;可以列出MySQL服务器运行各种状态值,我个人较喜欢的用法是show status like '查询值%';一、慢查询mysql> show variab
我的spring学习笔记7-Spring的Bean配置文件给Bean定义别名
aijuans
Spring 3
本文介绍如何给Spring的Bean配置文件的Bean定义别名?
原始的
<bean id="business" class="onlyfun.caterpillar.device.Business">
<property name="writer">
<ref b
高性能mysql 之 性能剖析
annan211
性能 mysql mysql 性能剖析 剖析
1 定义性能优化
mysql服务器性能,此处定义为 响应时间。
在解释性能优化之前,先来消除一个误解,很多人认为,性能优化就是降低cpu的利用率或者减少对资源的使用。
这是一个陷阱。
资源时用来消耗并用来工作的,所以有时候消耗更多的资源能够加快查询速度,保持cpu忙绿,这是必要的。很多时候发现
编译进了新版本的InnoDB之后,cpu利用率上升的很厉害,这并不
主外键和索引唯一性约束
百合不是茶
索引 唯一性约束 主外键约束 联机删除
目标;第一步;创建两张表 用户表和文章表
第二步;发表文章
1,建表;
---用户表 BlogUsers
--userID唯一的
--userName
--pwd
--sex
create
线程的调度
bijian1013
java 多线程 thread 线程的调度 java多线程
1. Java提供一个线程调度程序来监控程序中启动后进入可运行状态的所有线程。线程调度程序按照线程的优先级决定应调度哪些线程来执行。
2. 多数线程的调度是抢占式的(即我想中断程序运行就中断,不需要和将被中断的程序协商)
a) 
查看日志常用命令
bijian1013
linux 命令 unix
一.日志查找方法,可以用通配符查某台主机上的所有服务器grep "关键字" /wls/applogs/custom-*/error.log
二.查看日志常用命令1.grep '关键字' error.log:在error.log中搜索'关键字'2.grep -C10 '关键字' error.log:显示关键字前后10行记录3.grep '关键字' error.l
【持久化框架MyBatis3一】MyBatis版HelloWorld
bit1129
helloworld
MyBatis这个系列的文章,主要参考《Java Persistence with MyBatis 3》。
样例数据
本文以MySQL数据库为例,建立一个STUDENTS表,插入两条数据,然后进行单表的增删改查
CREATE TABLE STUDENTS
(
stud_id int(11) NOT NULL AUTO_INCREMENT,
【Hadoop十五】Hadoop Counter
bit1129
hadoop
1. 只有Map任务的Map Reduce Job
File System Counters
FILE: Number of bytes read=3629530
FILE: Number of bytes written=98312
FILE: Number of read operations=0
FILE: Number of lar
解决Tomcat数据连接池无法释放
ronin47
tomcat 连接池 优化
近段时间,公司的检测中心报表系统(SMC)的开发人员时不时找到我,说用户老是出现无法登录的情况。前些日子因为手头上 有Jboss集群的测试工作,发现用户不能登录时,都是在Tomcat中将这个项目Reload一下就好了,不过只是治标而已,因为大概几个小时之后又会 再次出现无法登录的情况。
今天上午,开发人员小毛又找到我,要我协助将这个问题根治一下,拖太久用户难保不投诉。
简单分析了一
java-75-二叉树两结点的最低共同父结点
bylijinnan
java
import java.util.LinkedList;
import java.util.List;
import ljn.help.*;
public class BTreeLowestParentOfTwoNodes {
public static void main(String[] args) {
/*
* node data is stored in
行业垂直搜索引擎网页抓取项目
carlwu
Lucene Nutch Heritrix Solr
公司有一个搜索引擎项目,希望各路高人有空来帮忙指导,谢谢!
这是详细需求:
(1) 通过提供的网站地址(大概100-200个网站),网页抓取程序能不断抓取网页和其它类型的文件(如Excel、PDF、Word、ppt及zip类型),并且程序能够根据事先提供的规则,过滤掉不相干的下载内容。
(2) 程序能够搜索这些抓取的内容,并能对这些抓取文件按照油田名进行分类,然后放到服务器不同的目录中。
[通讯与服务]在总带宽资源没有大幅增加之前,不适宜大幅度降低资费
comsci
资源
降低通讯服务资费,就意味着有更多的用户进入,就意味着通讯服务提供商要接待和服务更多的用户,在总体运维成本没有由于技术升级而大幅下降的情况下,这种降低资费的行为将导致每个用户的平均带宽不断下降,而享受到的服务质量也在下降,这对用户和服务商都是不利的。。。。。。。。
&nbs
Java时区转换及时间格式
Cwind
java
本文介绍Java API 中 Date, Calendar, TimeZone和DateFormat的使用,以及不同时区时间相互转化的方法和原理。
问题描述:
向处于不同时区的服务器发请求时需要考虑时区转换的问题。譬如,服务器位于东八区(北京时间,GMT+8:00),而身处东四区的用户想要查询当天的销售记录。则需把东四区的“今天”这个时间范围转换为服务器所在时区的时间范围。
readonly,只读,不可用
dashuaifu
js jsp disable readOnly readOnly
readOnly 和 readonly 不同,在做js开发时一定要注意函数大小写和jsp黄线的警告!!!我就经历过这么一件事:
使用readOnly在某些浏览器或同一浏览器不同版本有的可以实现“只读”功能,有的就不行,而且函数readOnly有黄线警告!!!就这样被折磨了不短时间!!!(期间使用过disable函数,但是发现disable函数之后后台接收不到前台的的数据!!!)
LABjs、RequireJS、SeaJS 介绍
dcj3sjt126com
js Web
LABjs 的核心是 LAB(Loading and Blocking):Loading 指异步并行加载,Blocking 是指同步等待执行。LABjs 通过优雅的语法(script 和 wait)实现了这两大特性,核心价值是性能优化。LABjs 是一个文件加载器。RequireJS 和 SeaJS 则是模块加载器,倡导的是一种模块化开发理念,核心价值是让 JavaScript 的模块化开发变得更
[应用结构]入口脚本
dcj3sjt126com
PHP yii2
入口脚本
入口脚本是应用启动流程中的第一环,一个应用(不管是网页应用还是控制台应用)只有一个入口脚本。终端用户的请求通过入口脚本实例化应用并将将请求转发到应用。
Web 应用的入口脚本必须放在终端用户能够访问的目录下,通常命名为 index.php,也可以使用 Web 服务器能定位到的其他名称。
控制台应用的入口脚本一般在应用根目录下命名为 yii(后缀为.php),该文
haoop shell命令
eksliang
hadoop hadoop shell
cat
chgrp
chmod
chown
copyFromLocal
copyToLocal
cp
du
dus
expunge
get
getmerge
ls
lsr
mkdir
movefromLocal
mv
put
rm
rmr
setrep
stat
tail
test
text
MultiStateView不同的状态下显示不同的界面
gundumw100
android
只要将指定的view放在该控件里面,可以该view在不同的状态下显示不同的界面,这对ListView很有用,比如加载界面,空白界面,错误界面。而且这些见面由你指定布局,非常灵活。
PS:ListView虽然可以设置一个EmptyView,但使用起来不方便,不灵活,有点累赘。
<com.kennyc.view.MultiStateView xmlns:android=&qu
jQuery实现页面内锚点平滑跳转
ini
JavaScript html jquery html5 css
平时我们做导航滚动到内容都是通过锚点来做,刷的一下就直接跳到内容了,没有一丝的滚动效果,而且 url 链接最后会有“小尾巴”,就像#keleyi,今天我就介绍一款 jquery 做的滚动的特效,既可以设置滚动速度,又可以在 url 链接上没有“小尾巴”。
效果体验:http://keleyi.com/keleyi/phtml/jqtexiao/37.htmHTML文件代码:
&
kafka offset迁移
kane_xie
kafka
在早前的kafka版本中(0.8.0),offset是被存储在zookeeper中的。
到当前版本(0.8.2)为止,kafka同时支持offset存储在zookeeper和offset manager(broker)中。
从官方的说明来看,未来offset的zookeeper存储将会被弃用。因此现有的基于kafka的项目如果今后计划保持更新的话,可以考虑在合适
android > 搭建 cordova 环境
mft8899
android
1 , 安装 node.js
http://nodejs.org
node -v 查看版本
2, 安装 npm
可以先从 https://github.com/isaacs/npm/tags 下载 源码 解压到
java封装的比较器,比较是否全相同,获取不同字段名字
qifeifei
非常实用的java比较器,贴上代码:
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
i
记录一些函数用法
.Aky.
位运算 PHP 数据库 函数 IP
高手们照旧忽略。
想弄个全天朝IP段数据库,找了个今天最新更新的国内所有运营商IP段,copy到文件,用文件函数,字符串函数把玩下。分割出startIp和endIp这样格式写入.txt文件,直接用phpmyadmin导入.csv文件的形式导入。(生命在于折腾,也许你们觉得我傻X,直接下载人家弄好的导入不就可以,做自己的菜鸟,让别人去说吧)
当然用到了ip2long()函数把字符串转为整型数
sublime text 3 rust
wudixiaotie
Sublime Text
1.sublime text 3 => install package => Rust
2.cd ~/.config/sublime-text-3/Packages
3.mkdir rust
4.git clone https://github.com/sp0/rust-style
5.cd rust-style
6.cargo build --release
7.ctrl