Java MongoDB 条件查询及其分组查询

    如果你已经搜索到了这个页面,那我很不幸的告诉你,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”来分组的),当然也可以多次分组,一层一层分,事实上,本人就用了三次分组,原理一样。

    欢迎大家留言!

你可能感兴趣的:(谷歌,m,Multimap,where条件)