如果你已经搜索到了这个页面,那我很不幸的告诉你,java mongodb的查询不仅慢,而且很繁琐,你的噩梦才刚刚开始。
先简单地介绍下,我要实现的功能。
本人一直在做网站运维这块,在统计网站数据的过程中,需要计算PV、UV,时间单位是一天,很自然就需要用到条件查询,查询一天的情况。
先看PV,查询某日总的页面访问量,面向页面计算。
/** * 查询某日PV量(总的页面访问量,面向页面) * @param date * @return PV量 */ public static int getPV(String strDate){ BasicDBObject query = new BasicDBObject(); int PV = 0; String condition = Condition.getTimeCond(strDate); query.put("$where",condition); dbCol = init(); DBCursor cursor = dbCol.find(query); while (cursor.hasNext()) { System.out.println(cursor.next());; } PV = cursor.count(); return PV; }再看UV,我以cookie中的UUID为标准,作为独立访客,00:00-24:00内相同的客户端只会被计算一次。
/** * UV(独立访客数)00:00-24:00内相同的客户端只会被计算一次 * @param strDate * @return UV量 */ public static int getUV(String strDate){ BasicDBObject query = new BasicDBObject(); int UV = 0; dbCol = init(); String condition = Condition.getTimeCond(strDate); query.put("$where",condition); //根据uuid去重,查询 UV = dbCol.distinct("uuid",query).size(); return UV; }如果你想偷懒,直接cope过去使用,肯定会报错的,呵呵呵!
我来稍带讲一下:
两个函数中的参数strDate,是你查询的日期,比如“2014-04-11”;
dbCol,是获取的集合对象,也就是DBCollection,这里不废话了,不知道的可以留言;
query,大家注意这个对象,它是用来临时条件查询中的条件,如果多个条件,也可以这样:
条件列表: BasicDBList condList = new BasicDBList(); //年龄大于1小于100 BasicDBObject cond1= new BasicDBObject(); cond1.append("age",new BasicDBObject("$gt",1)); cond1.append("age",new BasicDBObject("$lte",100)); //性别为女 BasicDBObject cond2= new BasicDBObject(); cond2.append("sex","女"); //将两个条件加入到条件集合中(多条件) condList.add(cond1); condList.add(cond2); BasicDBObject cond= new BasicDBObject(); cond.put("$and", condList); 然后查询数据: DBCursor cursor= coll.find(cond);condition,大家可能注意到了,这个对象是关键,标准的where条件从句,现在我将方法展示如下:
/** * 条件查询时间条件 * @param strDate * @return */ public static String getTimeCond(String strDate){ long mintime = DataFormat.stringToMills(strDate); long maxtime = mintime+86400000; return "function(){" +"var init = this.initTime.replace(new RegExp('-','gm'),'/'); " +"var initMills = (new Date(init)).getTime();" +"return initMills>"+mintime+"&&initMills<"+maxtime+";}" ; } }我将where条件用一个javascript函数返回,为什么可以这样呢,因为JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包,而mongodb存的就是类json数据(bson)。
还有在这里,我是把时间转换为了毫秒进行大小比较的!
最后一点,distinct函数,对就是sqlserver中的去重,很好用。
另外,讲讲分组。
先上代码:
//返回条件查询的游标 DBCursor cursor = dbCol.find(query); List<Map<String, String>> listOfMaps = new ArrayList(); //将游标中返回的结果记录到list集合中 while (cursor.hasNext()) { listOfMaps.add((Map<String, String>) cursor.next()); } //第一次分组,根据uuid分组 Multimap<String, Map<String, String>> partitionedMap = Multimaps.index( listOfMaps,new Function<Map<String, String>, String>() { public String apply(final Map<String, String> from) { return from.get("uuid"); } }); //将指定uuid下的每条记录添加到list集合中 List<Map<String, String>> useList = (List<Map<String, String>>) partitionedMap.get(uuid);不知道大家有没有用过guava,谷歌自创的map,很好用的。
官网:https://code.google.com/p/guava-libraries/
开源社区也有部分中文资料可供参考:http://www.oschina.net/question/tag/guava
uuid是本人在mongodb中一个字段名。
简单讲一下思路:先将条件查询获取的游标(只是指针)的结果遍历出来,然后放入一个List中,最后把list放入谷歌的Multimap中,就会返回分组后的结果(DEMO中from.get("uuid")是以“uuid”来分组的),当然也可以多次分组,一层一层分,事实上,本人就用了三次分组,原理一样。
欢迎大家留言!