”。
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特性)
如何在OpenCV Python中对图像执行位异或操作?
勤奋的可乐
Opencv opencv python 人工智能 计算机视觉 机器学习 神经网络 深度学习
彩色图像(RGB)有三个通道:红色、蓝色和绿色。图像表示为3维numpy数组。图像的像素值使用8位无符号整数(uint8)存储,范围为“0到255”。对两个图像执行位异或运算是在相应图像的像素值的二进制表示上执行的。以下是执行两个图像的位异或操作的语法–cv2.bitwise_xor(img1,img2,mask=None)这里,img1和img2是两个输入图像,mask是一个掩码操作。步骤要计算
Robyn与FastAPI全面对比:选择最适合你的Python Web框架
我就是全世界
fastapi python 前端
引言1.1背景介绍在当今的软件开发领域,选择合适的Web框架对于项目的成功至关重要。Python作为一种广泛使用的编程语言,其生态系统中涌现出了众多优秀的Web框架,如FastAPI和Robyn。FastAPI自发布以来,因其高性能、易用性和自动生成API文档的特性,迅速成为开发者的首选。而Robyn,作为一个结合了Python和Rust优势的新兴框架,以其异步处理能力和简洁的API设计,也吸引了
Python中的多线程实现与GIL(全局解释器锁)的影响
清水白石008
Python题库 python 开发语言 python 服务器 开发语言
Python中的多线程实现与GIL(全局解释器锁)的影响在Python编程中,多线程是一种常见的并发编程技术,它允许程序同时执行多个任务。然而,Python的全局解释器锁(GIL)对多线程的性能和并发性有着显著的影响。本文将深入探讨如何在Python中实现多线程,并详细解释GIL的影响,以及如何在实际编程中应对其带来的挑战。一、引言Python的多线程编程允许我们在一个进程中同时执行多个线程,从而
python中如何判断一个键是否在一个字典中,如果在打印输出在,用代码示例?
神笔馬良
python linux 前端
问题描述:python中如何判断一个键是否在一个字典中,如果在打印输出在,用代码示例?问题解答:在Python中,你可以使用in关键字来判断一个键是否存在于字典中。这个操作会返回一个布尔值,如果键存在于字典中则为True,否则为False。my_dict={'a':1,'b':2,'c':3}#判断键'a'是否在字典中if'a'inmy_dict:print("'a'存在于字典中")else:pr
Python GIL 全局解释器锁 详解
实相无相
python教程 python GIL 全局解释器锁
PythonGIL详解在Python的多线程编程中,一个常被提及的概念是全局解释器锁(GIL,GlobalInterpreterLock)。它是Python解释器设计中的一个重要特性,对多线程应用的性能和行为产生了深远影响。在这篇文章中,我们将深入探讨GIL的工作原理、影响、以及如何在Python编程中应对这一限制。什么是GIL?GIL是Python解释器的一种锁机制,主要用于保护对Python对
Python ORM
svygh123
python 编程 python 开发语言
Python中的ORM(Object-RelationalMapping)框架,其中最著名和广泛使用的两个是SQLAlchemy和DjangoORM。1.SQLAlchemySQLAlchemy是Python中功能最强大的SQL工具库之一,它不仅提供了ORM功能,还提供了核心的数据库SQL工具。它允许你用Python类来表示数据库表,并且可以使用Python代码而不是直接写SQL查询语句来操作数据
C#上位机开发,串口通信,读写数据以及处理
luckyext
c# 开发语言 硬件工程 物联网
在自动化、物联网以及工业控制行业中,上位机开发是一项重要的技能。本教程主要介绍使用C#进行上位机开发,重点在于串口通信和数据处理。串口通信是一种常见的方式,允许设备之间通过串行接口交换数据,例如RS232、RS485等。在C#中,System.IO.Ports命名空间提供了SerialPort类,用于实现串口通信。创建`SerialPort`对象时,需要指定端口号、波特率、数据位、停止位和校验位。
CentOS下的软件安装及卸载,yum命令常用方法及常见问题
luckyext
centos linux 运维 服务器
CentOS中安装及卸载软件,常用yum命令安装及卸载软件包。yum(YellowdogUpdater,Modified)是基于RPM的软件包管理器,可用于在CentOS中安装、更新、查询和移除软件包。yum命令可以从指定服务器下载rpm包并安装,能自动解决依赖问题。1.安装软件包yuminstall-y参数:安装过程中不提示,自动回答所有提问为“yes”。例如安装nginx:yuminsta
在Python中使用“判断字典键是否存在的方法“进行键的查找
代码之旅创造者
python 开发语言 Python
在Python编程中,经常需要在字典中查找某个特定的键是否存在。字典是Python中常用的数据结构之一,它由一系列键-值对组成,每个键都是唯一的。为了判断一个键是否存在于字典中,我们可以使用in关键字或has_key()方法。下面将介绍如何使用in关键字和has_key()方法来判断键是否存在,并提供相应的源代码示例。使用in关键字判断键是否存在在Python中,使用in关键字可以判断一个键是否存
炸裂!Linux内核代码疯长,十年翻倍直逼4000万行!
盼达思文体科创
经验分享
引言在科技的浩瀚宇宙中,操作系统宛如一颗核心恒星,照亮了整个数字世界。而Linux内核,作为众多操作系统的基石,一直以来都扮演着至关重要的角色。它不仅是开源精神的象征,更是无数开发者智慧的结晶。想象一下,我们日常使用的智能手机、电脑,甚至是汽车、家电里的智能系统,很多都离不开Linux内核的支持。它就像一个看不见的大管家,默默管理着设备的各种资源,让一切都能有条不紊地运行。如今,Linux内核代码
鸿蒙HarmonyOS实战-ArkUI动画(页面转场动画)_鸿蒙arkui tab 切换动画
字节全栈_OYI
harmonyos 华为
PageTransitionExit({type?:RouteType,duration?:number,curve?:Curve|string,delay?:number})在HarmonyOS中,PageTransitionEnter和PageTransitionExit是用于控制页面切换动画的参数。它们分别表示页面进入和退出时的动画。1.type(动画类型):表示动画的类型,可以取以下几种值
商品价格跟踪爬虫:监控多个电商网站的商品价格波动
Python爬虫项目
2025年爬虫实战项目 爬虫 python 开发语言
1.引言在当前的电商环境中,商品价格变化快速且频繁。对于消费者而言,能够实时跟踪商品价格的波动是一项非常实用的功能。而对于商家来说,了解竞争对手的价格走势也是一种重要的商业策略。因此,开发一个商品价格跟踪爬虫,能够帮助我们及时掌握价格动态。本文将详细介绍如何使用Python实现一个高效的商品价格跟踪爬虫,并对多个电商网站进行价格监控。2.爬虫概述爬虫的作用是模拟浏览器向目标网站发送请求,获取商品页
Python字典的键是否可以相同?
雪域Code
python linux 开发语言 Python
解密Python字典的键是否可以相同的疑问,带你深入了解字典的特性。在Python中,字典是一种无序的数据结构,它由键值对组成,其中键是唯一的。这意味着每个键只能在字典中出现一次。当尝试使用相同的键插入或更新字典时,后面的键值对会覆盖前面的。让我们通过源代码来验证这一点:my_dict={'key1':'value1','key2':'value2','key1':
[python]判断键是否在字典中
FL1623863129
Python python 开发语言
在Python中,检查字典中是否存在某个键可通过以下方法实现:使用in关键字:最常用且直接,检查键是否存在于字典的键集合中。my_dict={'a':1,'b':2}if'a'inmy_dict:print("Key'a'exists.")else:print("Key'a'doesnotexist.")使用get()方法:尝试获取键对应的值,若键不存在则返回默认值(默认为None)。通过返回值是
python中什么意思_#python3type(1)为什么和python核心编程里的不一样?...
weixin_39906245
'int'>什么意思
补充一点,type是个对象,type(1)也是个对象在交互环境下输出type(1)或者print(type(1))相当于type.__repr__(int)和type.__str__(int)下面说的“统一”,我想说的是python2里type的输出会有和两种情况,这应该是由于历史原因吧(旧式类和新式类,下面的引用和链接里也有相关的内容),然后python3里没有了旧式类,就达成了统一classF
【Python 笔记2】os.path.join()
挪威的深林
Python笔记 python
0.前言os.path.join()函数是Python中处理文件和目录路径的非常重要和常用的方法。它可以自动处理不同操作系统之间在路径分隔符方面的差异,从而使代码更加可移植和易于维护。下面我将详细解释每个用法,并提供示例代码。1.合并路径组件基本用法是将多个路径组件合并成一个完整的路径。这个方法会根据你的操作系统选择正确的路径分隔符。importospath=os.path.join("path"
理解 Python 解释器:CPython 与 IPython 的比较及选择指南
YRr YRr
python python ipython 开发语言
理解Python解释器:CPython与IPython的比较及选择指南在选择适合自己需求的Python解释器时,理解CPython和IPython之间的主要差异至关重要。本文将详细解释CPython和IPython的特性、优势和适用场景,以帮助用户做出明智的选择。1.CPython:Python的默认解释器特点官方标准:CPython是Python语言的官方参考实现,由Python软件基金会维护。
打架检测系统:基于YOLOv5的实时人群打架行为识别
2025年数学建模美赛
YOLO 深度学习 ui 计算机视觉 视觉检测
1.引言打架检测,作为一个复杂且具有挑战性的任务,已经在多个领域展现出其巨大的应用潜力,尤其是在公共安全监控、安防摄像头、智能城市等应用场景中。通过深度学习技术,尤其是基于YOLOv5的目标检测,我们能够对实时视频流中的人群行为进行实时监控,并有效地检测和识别人群中的打架行为。本博客将详细介绍如何使用YOLOv5模型搭建一个打架检测系统,包含数据集准备、YOLOv5训练、UI界面设计以及优化和部署
XSLT `<value-of>` 元素详解
lly202406
开发语言
XSLT元素详解XSLT(可扩展样式表语言转换)是一种用于将XML文档转换为其他格式(如HTML或纯文本)的语言。在XSLT中,元素是一个非常有用的元素,它允许开发者从XML源文档中提取特定值。本文将详细介绍元素的用法、属性以及在实际应用中的示例。1.元素概述元素是XSLT中用于提取XML源文档中数据的常用元素。它可以将XML源文档中的节点值转换为其他格式,如字符串、数字等。下面是元素的语法:其中
Vue3 表单:全面解析与最佳实践
lly202406
开发语言
Vue3表单:全面解析与最佳实践引言随着前端技术的发展,Vue.js已经成为最受欢迎的前端框架之一。Vue3作为Vue.js的最新版本,带来了许多改进和新的特性。其中,表单处理是Vue应用中不可或缺的一部分。本文将全面解析Vue3中的表单处理,包括基础用法、表单验证、双向绑定等,并提供一些最佳实践。Vue3表单基础1.1创建表单在Vue3中,创建表单非常简单。首先,我们需要定义一个元素,并为其绑定
探索ImGui Knobs:打造直观的交互式控制面板
倪澄莹George
探索ImGuiKnobs:打造直观的交互式控制面板imgui-knobsKnobwidgetsforDearImGui项目地址:https://gitcode.com/gh_mirrors/im/imgui-knobs在数字创意和应用程序开发的世界中,用户体验往往决定了一个应用的成功与否。今天,我们要介绍一款神器——ImGuiKnobs,它将为你的C++项目增添一抹创新的光彩。项目介绍ImGuiK
Java循环操作哪个快
eqa11
java
文章目录Java循环操作哪个快一、引言二、循环操作性能对比1、普通`for`循环与增强`for`循环1.1、代码示例2、`for`循环与`while`循环2.1、代码示例3、循环优化技巧3.1、代码示例三、循环操作的适用场景四、使用示例五、总结Java循环操作哪个快一、引言在Java开发中,循环操作是常见的编程任务,但不同的循环方式在性能上存在差异。选择合适的循环结构对于优化程序性能至关重要。本文
一文讲解Spring中应用的设计模式
Journey_CR
Spring spring 设计模式 java
我们都知道Spring框架中用了蛮多设计模式的:工厂模式呢,就是用来创建对象的,把对象的创建和使用分开,这样代码更灵活。代理模式呢,是用一个代理对象来控制对真实对象的访问,可以在访问前后做一些处理。单例模式呢,保证一个类只有一个实例,比如数据库连接池就经常用单例模式。模板模式呢,定义一个算法的框架,把具体的实现延迟到子类去做。观察者模式呢,定义了对象之间的一对多依赖关系,当一个对象状态改变时,依赖
Python中os.path模块的使用详解
幻想世界中的绚丽色彩
python 开发语言 Python
os.path模块是Python标准库中的一个模块,提供了用于处理文件路径和名称的函数。它是处理操作系统相关的路径的理想选择,无论是在Windows、Linux还是其他操作系统上。本文将详细介绍os.path模块的常用函数及其用法,并提供相应的源代码示例。获取文件名和目录名os.path模块提供了一些函数来获取文件路径的各个部分,如目录名、文件名和扩展名等。importospath='/path/
面试常考题目——状态码总结
字节全栈_BjO
面试 职场和发展
这是个面试和考研的算法练习我们一起加油上岸之路总述=====================================================================1开头这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。由于HTTP/1.0协议中没有定义任何1xx状态码,所以除非在某些试验条件下,服务器禁
Android岗常见40道面试题,面试前必须了解的知识点!!!
2501_90226046
android 面试 职场和发展
2)Thread普通线程,如果需要有自己的消息队列,需要调用Looper.prepare()创建Looper实例,调用loop()去循环消息。3)HandlerThread是一个带有Looper的线程,在HandleThread的run()方法中调用了Looper.prepare()创建了Looper实例,并调用Looper.loop()开启了Loop循环,循环从消息队列中获取消息并交由Handl
深入探索 HTML5 拖拽效果 API:打造流畅交互体验
山禾女鬼001
html5 前端 html
在现代的Web开发中,交互性和用户体验一直是开发者关注的重点。HTML5的拖拽效果API(DragandDropAPI)提供了一种非常直观的方式来让网页元素或文件能够被拖动并放置到页面的指定位置,极大提升了用户的交互体验。本篇文章将深入探讨如何使用HTML5拖拽API来实现拖拽效果,帮助开发者理解并掌握这一强大的工具。一、HTML5拖拽API简介HTML5的拖拽API允许用户通过鼠标或触摸屏等设备
Python中os.path.join函数的用法示例详解
阿鈞ajunwiwx
谜之操作 python 人工智能 目标检测 opencv 机器学习
前言仅供个人学习用,如果对各位朋友有参考价值,给个赞或者收藏吧^_^一、os.path.join函数os.path.join函数用于拼接多个路径字符串,生成一个新的路径字符串。用法:os.path.join(path,*paths)二、函数用法个人总结1.处理不同操作系统的路径分隔符。2.从右往左看参数,如果一个参数无‘/’或者‘\’,则按照操作系统用分隔符,如果遇到,则左边参数均会被舍弃。3.从
ROS发行版
虎啸~嘤嘤嘤
机器人 自动驾驶 人工智能
ROS是一个用于机器人软件开发的灵活框架,它支持多种编程语言,并且其不同的版本(称为“发行版”)提供了不同的特性和兼容性。foxy是ROS2的一个发行版名称。ROS2是ROS的一个新版本,它引入了新的通信机制(如DDS,DataDistributionService)、更好的系统架构和更多的现代编程语言支持(如C++11、Python3等)。foxy是在特定时间点上发布的ROS2的一个版本,它包含
MySQL存储结构的使用
weixin_30814223
数据库
前言今天公司老大让我做一个MySQL的调研工作,是关于MySQL的存储结构的使用。这里我会通过3个例子来介绍一下MySQL中存储结构的使用过程,以及一些需要注意的点。笔者环境系统:Windows7MySQL:MySQL5.0.96准备工作1.新建两张数据表:student1,student2新建student1DROPTABLEIFEXISTSstudent1;CREATETABLEstudent
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