”。
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特性)
Android和IOS应用开发-Flutter应用让屏幕在 app 运行期间保持常亮的方法
江上清风山间明月
Flutter android ios flutter KeepAlive 屏幕常亮 wakelock 熄屏
文章目录Flutter应用让屏幕在app运行期间保持常亮的方法方法一:使用系统插件方法二:使用Widgets注意事项Flutter应用让屏幕在app运行期间保持常亮的方法在Flutter开发中,可以使用以下两种方法让屏幕在app运行期间保持常亮:方法一:使用系统插件Flutter社区中已经有很多相关插件可供使用,比如wakelock:https://pub.dev/packages/wakeloc
微信小程序监听用户经纬度变化
某公司摸鱼前端
微信小程序 小程序
一些打卡App需要根据用户的位置来完成打卡那么就需要监听用户位置变化情况:示例://在某个生命周期函数中,如onLoad中onLoad:function(options){//开始监听位置变化wx.startLocationUpdate({success:function(){console.log('开始更新位置');},fail:function(){console.log('开始更新位置失败
2019-04-08早
梦雅的简动力
在上瑜伽课前10分钟的调息中,你的眼睛为什么总是想睁开?(焦虑)。你的眉头为什么总是紧锁?(压力)。练习体式时你为什么总是去看别人?(攀比)保持体式时你为什么总是烦躁?(性急)。保持长久而规律的练习,以上这些,终归离你远去。瑜伽,首先,不是帮你得到,而是教你放下。图片发自App时间,一时间无法跳离这个特殊的词汇毅力,坚持,真诚,需要时间来见证真相,现实,伪装,时间自然会揭秘珍惜它又害怕它可它丝毫不
教育微创新的意蕴
知北老师
我是1992年参加工作的,一毕业就被分配到一所全县最偏僻落后的农村学校——付窝中学,12年后被调往一所已经连续十年全县倒数第一,也是很偏僻落后的农村学校——北宋镇第三中学。三年后到了北宋镇第一中学工作,这所学校教学质量也是连续几年落后了。2014年我到了北京市育英学校,这所学校是京城名校。2016年7月,我被育英学校派往原密云区第七中学工作,这是一所城乡接合部薄弱学校。学校现名为北京市育英学校密云
【OpenModelica】4命令行大全
Wumbuk
python 开发语言 modelica
命令行大全文章目录命令行大全一、SummaryofCommandsfortheInteractiveSessionHandler二、Runningthecompilerfromcommandline一、SummaryofCommandsfortheInteractiveSessionHandler以下是交互式会话处理器中当前可用命令的完整列表。•simulate(modelname):翻译一个名为
通俗易懂:MySQL中如何设置只读实例并确保数据一致性?
大龄下岗程序员
mysql java mysql spring
在MySQL中设置只读实例主要应用于构建高可用性和扩展性的数据库环境,通常是为了分担读取负载或者用于备份和灾难恢复。以下是创建MySQL只读实例并确保数据一致性的基本步骤:1.创建并配置只读实例-主从复制设置-首先,你需要有一个主数据库实例(Master)负责接收所有的写操作。-创建一个或多个从数据库实例(Slave),并将它们配置为主数据库的复制品。这通常通过设置主从复制(Replication
拼多多纸巾推荐:品质与性价比的完美结合
氧惠帮朋友一起省
拼多多纸巾推荐拼多多纸巾返现怎么做在我们的日常生活中,纸巾已经成为不可或缺的用品。无论是在家庭、办公室还是旅途中,纸巾都是我们随时随地需要的物品。随着电商平台的兴起,越来越多的人选择在网上购买纸巾。其中,拼多多作为国内知名的电商平台之一,以其独特的社交电商模式和实惠的价格吸引了大量用户。今天,我们就来探讨如何在拼多多上选择品质优良、性价比高的纸巾,以及如何通过一些小技巧来获取更多的优惠。一、品质与
LeetCode1047:删除字符串中的所有相邻重复项
一个小猴子`
LeetCode 算法 数据结构 c++ leetcode
题目描述给出由小写字母组成的字符串S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在S上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。示例:输入:“abbaca”输出:“ca”解释:例如,在“abbaca”中,我们可以删除“bb”由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串“aaca”,其中又只有“a
Mac命令行查找SDK/JDK安装位置
iblade
Linux macos java 开发语言
要在命令行中查询AndroidSDKPlatformTools的安装位置,可以使用以下步骤:使用which命令:在命令行中执行以下命令:whichadb这将输出adb命令的安装路径,通常情况下,它会在AndroidSDK的platform-tools目录下。手动查找:如果whichadb没有输出,可以手动查找AndroidSDK的安装位置。通常情况下,AndroidSDK的默认安装路径是在用户的h
易经第六十一卦风泽中孚
徐徐微风正好
易经第六十一卦风泽中孚,巽上兑下。中孚:豚鱼吉,利涉大川,利贞。中孚卦象征着中心诚信,甚至诚信到了能够感动小猪小鱼,可获吉祥,对渡过大河巨流有利,对坚守正道有利。诚信是立人之本,立身处世心怀诚信广施仁义才会走的长远。但是诚信也要合理合时,君子从中得到启示,要以诚信的德行慎重审议案件并宽缓死刑。诚信可以使人信服,有利于坚守中正,内在谦逊柔顺外在坚守行动诚信,连最顽固的老百姓都被感化,天何言哉,四时行
读思001 ‖ 变负能为正能,变压力为动力
你不懂夜的黑
今天起开始写一个言说文集连载,重点为读写思考收获和感想,也收录生活和工作中开悟到的点滴,仍然是一个碎片式的思考积累。希望这样的思考能启迪我的生活智慧,开悟我的思想境界,也算是一个修心的过程吧。这个连载不定期更新,重在积累生活和工作中的随思碎思,或许也是一厢情愿的一个梦。也或许这个梦是我坚持说下去的一个重要理由。读思001变负能为正能,变压力为动力1从来没有一种哲学能解决一切问题,也从来没有一种药能
学习JavaEE的日子 Day32 线程池
A 北枝
学习JavaEE 学习 java-ee java 线程池
Day32线程池1.引入一个线程完成一项任务所需时间为:创建线程时间-Time1线程中执行任务的时间-Time2销毁线程时间-Time32.为什么需要线程池(重要)线程池技术正是关注如何缩短或调整Time1和Time3的时间,从而提高程序的性能。项目中可以把Time1,T3分别安排在项目的启动和结束的时间段或者一些空闲的时间段线程池不仅调整Time1,Time3产生的时间段,而且它还显著减少了创建
淘宝天猫38节活动时间和玩法,2024年焕新周满减优惠多少
小小编007
在2024年,淘宝天猫平台即将迎来一年一度的38节活动,这是广大消费者们翘首以待的购物狂欢节。在这篇文章中,我们将为您详细解读淘宝天猫38节活动的时间安排和玩法,以及2024年焕新周的满减优惠力度。一、淘宝天猫38节活动时间2024年淘宝天猫38节活动将于2月28日正式启动,持续至3月8日,为期10天。活动期间,消费者们可以尽情享受各种优惠折扣、满减活动以及限时秒杀,尽情释放购物热情。2024淘宝
黔东南——苗年(一)
非常道yw
苗年是雷山县苗族同胞最隆重的民族传统节日,也是苗族人一年中庆祝丰收和最重要的祭祀性的日子,更是雷山苗族一年里劳作的结束和欢乐的开始。如同汉族的春节。节日期间,各村寨都要举行跳芦笙、篮球赛、斗牛、赛马、斗鸟、铜鼓舞、篝火晚会等民间传统娱乐活动。苗年也是最集中地展示苗族服饰、银饰、手工艺美术等有形文化的节日,时间大都在农历十月。苗族认为,一年只有热、冷两个季节,热季和冷季交替的农历十月,既是热季的结束
SpringMVC设置全局异常处理器
水岸齐天
java spring
文章目录背景分析使用@ControllerAdvice(@RestControllerAdvice)+@ExceptionHandler实现全局异常全局异常处理-多个处理器匹配顺序存在一个类中存在不同的类中对于过滤器和拦截器中的异常,有两种思路可以考虑背景在项目中我们有需求做一个全局异常处理,来规范所有出去的异常信息。参考:官方文档分析首先ControllerAdvice(RestControll
安神的投资札记——指数跟踪周报(20220602)
echo安神
本周关键词:缩表上周调整过后,本周又反弹了。最近创业板好活跃,跌的时候跌得凶,涨的时候也涨得猛。底部特征明显。上证50,0.99%;沪深300,2.21%;中证100,1.85%;中证500,3.03%;深证100,3.71%;创业板指数,5.85%;中证1000,3.75%。美联储6月1日开启缩表,每月总计减持475亿美元美国国债和MBS(抵押贷款支持证券),并将在3个月后提高缩表上限至每月95
【算法分析与设计】去除重复字母
五敷有你
算法分析与设计 java javascript 开发语言 算法 数据结构
个人主页:五敷有你系列专栏:算法分析与设计⛺️稳中求进,晒太阳题目给你一个字符串s,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。示例示例1:输入:s="bcabc"输出:"abc"示例2:输入:s="cbacdcbc"输出:"acdb"思路贪心+单调栈实现【字符串删除一个字符使其字典序最小的贪心策略】:对于两个长度相同的字符串,
以前开发MFC界面如何快速转成QT界面
广州视觉芯软件有限公司
mfc qt c++
将MFC界面快速转换为Qt界面可能需要进行一些手动工作,因为MFC和Qt是两个不同的界面框架,它们具有不同的设计和实现原理。但是,以下步骤可以帮助你快速进行转换:创建一个新的Qt项目:使用QtCreator创建一个新的Qt项目。分析MFC界面:仔细分析你的MFC界面,包括窗口、对话框、控件等的布局、样式和行为。重新设计界面:使用Qt的可视化设计器重新设计界面。在QtCreator的设计器中,你可以
c++中如何判断变量的数据类型,并输出
xnrbjy
c++ 开发语言
C++中如果想要判断变量的数据类型,可以使用typeid运算符。该运算符返回一个std::type_info类型的对象,可以使用name()方法获取其名称从而确定变量的类型,例如:#include#includeusingnamespacestd;intmain(){inta=123;floatb=3.14;boolc=true;chard='A';stringe="HelloWorld";cou
为千 佩蓉:为家庭放弃事业的男人没出息吗?
北京朵多教育
为家庭放弃事业的男人没出息吗我们在搭档的过程中会遇到一些问题,因此要做好心理准备,这样才不会陷入抱怨或双输的局面。关键不是谁比谁能力强,而是夫妻之间如何取长补短。家庭要赢需要每个人的付出和牺牲,大家一起分担和负责,这样才能享受相爱的自由、安全和归属感。我们需要做的牺牲包括自己的时间、自己的一些爱好,甚至事业发展。为千认为做好父亲是非常重要的事,所以他不仅要出席在孩子们的生活中,还要积极地参与和带领
CSV指南:Python程序获取大型CSV文件行数
孤独打铁匠Julian
笔记 经验分享 python
本指南提供了几种使用Python来获取大型CSV文件行数的方法,并解释了每种方法的适用场景。方法1:使用csv.reader处理复杂CSV文件当你的CSV文件中包含多行字段(即某些字段的值中包含换行符)时,使用csv.reader是一个可靠的选择,因为它能够正确处理这些复杂情况。这个方法适用于大多数大小的CSV文件,但是对于非常大的文件,读取整个文件可能会占用较多的时间和内存。对于极大的文件,考虑
什么事都独自去扛的人,容易抑郁,以及单身
蘑菇心理
文|实用菌01心情不好的时候,你会怎么办?我的习惯是,找个没有人打扰的角落发呆,或者睡上一觉。生活中,这样处理自己情绪问题的人,还有很多。他们安静,平和,不吵不闹,看起来很佛系,甚至还被称赞你脾气好,内心成熟,但事实,这种外在的好是以一些隐蔽的“坏”为代价的。遇到问题习惯独自去承受的人,表面看起来很坚强,但有一个弱点:在日常生活中,他们的情绪经常会莫名地低落,没来由地不高兴,而且一旦陷入这种情绪当
200719:重拾优点?
问谁逝舟
小时候的哪些优点,现在想重新拾回?——题记:《惜福阅历(SisypheCalendar)》2020.01.04还是先来审题吧。这句话中的关键信息就在于“重拾小时候的优点”。小时候的优点,当然是在曾经的生活中,给我们带来过好处,有其被自己或是被社会认可的价值。而它跟“重拾”搭配在一起,就颇耐人寻味了。重拾,意味着曾经失落,也意味着它对当下还有价值。那么问题来了,既然曾经它是有价值的,既然对当下还有价
闺蜜闲聊
青儿小语
今天几位闺蜜相聚。抛下家务,老公,孩子,一起来到一个山清水秀的地方,在湖边畅聊。但聊来聊去发现,我们的话题跑不出孩子和老公,除此之外就没有什么了。这是一种人到中年的悲哀吗,女人在家庭中渐渐失去了自己,所以的生活重心都不在自己这里,我们把小小我融入了大家,小家,姐妹们畅聊一番,放松自己,回去还得应对家里的鸡飞狗跳,一地鸡毛。
matlab按行读取txt文件数据集
地上悬河
matlab 开发语言
功能:使用Matlab按行读取txt文件,按照特定符号进行分割后加入数组中fid=fopen('coordinate.txt');%首先打开文本文件coordinate.txttemp=[]while~feof(fid)%while循环表示文件指针没到达末尾,则继续%每次读取一行,str是字符串格式str=fgetl(fid);%以','作为分割数据的字符,结果为cell数组s=regexp(st
C#中的PLINQ和LINQ的效率对比
搬砖的诗人Z
C# c# linq 开发语言
PLINQ(ParallelLINQ)和LINQ(LanguageIntegratedQuery)都是.NET框架中的功能,用于对集合进行查询和操作。它们之间的主要区别在于并行处理能力。LINQ:LINQ是一种用于在.NET应用程序中进行数据查询和操作的语言集成功能。它提供了一种统一的方式来查询各种数据源,如集合、数组、XML、数据库等。LINQ是在单线程环境中执行查询操作的,因此对于大型数据集或
chrome扩展,“manifest_version“: 3, chrome 扩展图标点击事件
徐同保
chrome 前端
在Chrome扩展中,从ManifestV3开始,后台脚本(backgroundscripts)被服务工作线程(serviceworkers)所取代。这改变了扩展图标点击事件(通常称为浏览器操作或者页面操作)的处理方式。在ManifestV3中,您需要使用chrome.action.onClicked监听器来处理扩展图标的点击事件。下面是一个如何设置扩展图标点击事件处理器的示例:在manifest
地低为海人低为王
缘梦草
地低为海,人低为王。低,高之基,高,低之顶。谦虚才能收益,咄咄逼人会招损。高粱熟了,头会低下。受益反而会深藏不露。捧人之术,把人捧高,然后控制。受控之人,大都是虚荣心作祟。活成别人想象中的样子,像别人想象中那么有面子的活着是悲哀的。穷不可怕,怕的是虚荣心。当你好面子,你就会被控制。一旦受虚荣心控制,你不得不谨小慎微的维护面子,付出多余的能量,希望得到别人的一句赞。面子就是金子打造的牢笼,让你在赞美
请简单介绍一下Shiro框架是什么?Shiro在Java安全领域的主要作用是什么?Shiro主要提供了哪些安全功能?
AaronWang94
shiro java java 安全 开发语言
请简单介绍一下Shiro框架是什么?Shiro框架是一个强大且灵活的开源安全框架,为Java应用程序提供了全面的安全解决方案。它主要用于身份验证、授权、加密和会话管理等功能,可以轻松地集成到任何JavaWeb应用程序中,并提供了易于理解和使用的API,使开发人员能够快速实现安全特性。Shiro的核心组件包括Subject、SecurityManager和Realms。Subject代表了当前与应用
linux基础命令(一)
运维搬运工
linux linux 服务器 centos
Linux基础命令1、设置主机名1.1、hostname查看主机名[root@ansible~]#cat/etc/hostnameansible或[root@ansible~]#hostnameansible注意:主机名中不允许使用下划线“_”,可以用短横线“-”1.2、hostname临时修改主机名#临时修改直接修改的是内存中的,重启会失效[root@ansible~]#hostnameansi
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