1. 程式人生 > >java:Mongodb 分組統計應用group的使用(含場景)

java:Mongodb 分組統計應用group的使用(含場景)

------------------------場景-----------------

mongodb中資料集合(ABC123)包含的指標進行統計分析,指標(指標在mongodb中實際以字母、數字組合的編碼表示)包括:
A1:使用者標識、A2:使用者編碼、A3:使用者名稱稱、A4:地市、A5:區縣、A6:手機號碼、A7:賬期、A8:入網時間、A9:ARPU值

需地市、區縣分組統計的指標(統計指標的結果標識編碼可自定義):
X1:使用者數、X2:總ARPU值、X3:平均使用者入網時間

即需要統計分析:
使用者數:      count(使用者編碼)
總ARPU值:     sum(ARPU值)
平均入網時間:sum(入網時間)/count(使用者編碼)

----------------------------------------------

mongodb  java  api   mongo-2.7.3.jar
mongodb group 分組函式使用:
BasicDBList basicDBList = (BasicDBList)db.getCollection("mongodb中集合編碼或者編碼")
                   .group(DBObject key,   --分組欄位,即group by的欄位
                DBObject cond,        --查詢中where條件
                DBObject initial,     --初始化各欄位的值
                String reduce,        --每個分組都需要執行的Function
                String finial         --終結Funciton對結果進行最終的處理
);

------------------------程式碼------------------------------

將分組欄位、統計的結果欄位、統計公式中用到的欄位分別儲存在HashMap中:
分組欄位:
HashMap dimMap = new HashMap();
dimMap.put("A4","A4");    //地市
dimMap.put("A5","A5");    //區縣

統計的結果欄位:
HashMap forIdxMap = new HashMap();
dimMap.put("X1","count(A2)");            //使用者數
dimMap.put("X2","sum(A9)");              //總ARPU值
dimMap.put("X3","sum(A8)/count(A2)");    //平均使用者入網時間

統計公式中用到的欄位:
HashMap indexMap = new HashMap();
dimMap.put("A2","A2");            //使用者編碼
dimMap.put("A8","A8");            //入網時間
dimMap.put("A9","A9");            //ARPU值

java呼叫:
BasicDBList basicDBList = (BasicDBList)db.getCollection("ABC123")
                   .group(GroupUtil.generateFormulaKeyObject(dimMap),
                       new BasicDBObject(),
                        GroupUtil.generateFormulaInitObject(indexMap),
                         GroupUtil.generateFormulaReduceObject(indexMap),
                          GroupUtil.generateFormulaFinalizeObject(forIdxMap, indexMap));

GroupUtil.java:

package com.test;

import java.util.HashMap;
import java.util.Iterator;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

public class GroupUtil
{
	/**
	 * 方法描述:根據使用者選擇的維度編碼和指標編碼,生成Group中的key
	 * @param dimMap 維度編碼
	 * @return key 物件
	 */
	public static DBObject generateFormulaKeyObject(HashMap dimMap)
	{
		DBObject key = new BasicDBObject();
		Iterator dimIt = dimMap.keySet().iterator();
		while (dimIt.hasNext())
		{
			String dimId = (String)dimIt.next();
			key.put(dimId, true);
		}
		return key;
	}
	
	/**
	 * 方法描述:根據使用者選擇的維度編碼和指標編碼,生成Group中的屬性初始化值
	 * @param dimMap 維度編碼
	 * @return key 物件
	 */
	public static DBObject generateFormulaInitObject(HashMap indexMap)
	{
		DBObject initial = new BasicDBObject();
		//設定計算指標中使用的指標對應的統計值:sum、count、avg、max、min
		Iterator indexIt = indexMap.keySet().iterator();
		while (indexIt.hasNext())
		{
			DBObject index = new BasicDBObject();
			index.put("count", 0);
			index.put("sum", 0);
			index.put("max", 0);
			index.put("min", 0);
			index.put("avg", 0);
			index.put("self", 0);
			String indexId = (String)indexIt.next();
			initial.put(indexId, index);
		}
		
		return initial;
	}
	
	/**
	 * 方法描述:根據使用者選擇的指標編碼,生成Group中的reduce函式
	 * @param indexMap 指標編碼
	 * @return reduce函式
	 */
	public static String generateFormulaReduceObject(HashMap indexMap)
	{
		StringBuffer reduceBuf = new StringBuffer();
		
		reduceBuf.append("function(doc, prev) {");
		reduceBuf.append("var tempVal;");
		Iterator indexIt = indexMap.keySet().iterator();
		while (indexIt.hasNext())
		{
			String indexId = (String)indexIt.next();
			//計算指標數量
			reduceBuf.append("prev.").append(indexId).append(".count ++;");
			//計算指標總計
			reduceBuf.append("if(isNaN(").append("prev.").append(indexId).append(".sum").append(")){");
			reduceBuf.append("prev.").append(indexId).append(".sum = 0;");
			reduceBuf.append("}");
			reduceBuf.append("prev.").append(indexId).append(".sum += parseFloat(doc.").append(indexId).append(");");
			reduceBuf.append("if(isNaN(").append("prev.").append(indexId).append(".self").append(")){");
			reduceBuf.append("prev.").append(indexId).append(".self = 0;");
			reduceBuf.append("}");
			reduceBuf.append("prev.").append(indexId).append(".self = parseFloat(doc.").append(indexId).append(");");
			
			reduceBuf.append("print(prev.").append(indexId).append(".self);");
			//計算指標最大值
			reduceBuf.append("tempVal = parseFloat(doc.").append(indexId).append(");");
			reduceBuf.append("if(").append("prev.").append(indexId).append(".max == 0").append("){");
			reduceBuf.append("prev.").append(indexId).append(".max = tempVal;");
			reduceBuf.append("}else{");
			reduceBuf.append("prev.").append(indexId).append(".max = ");
			reduceBuf.append("prev.").append(indexId).append(".max > tempVal ? ");
			reduceBuf.append("prev.").append(indexId).append(".max : tempVal;");
			reduceBuf.append("}");
			//計算指標最小值
			reduceBuf.append("if(").append("prev.").append(indexId).append(".min == 0").append("){");
			reduceBuf.append("prev.").append(indexId).append(".min = tempVal;");
			reduceBuf.append("}else{");
			reduceBuf.append("prev.").append(indexId).append(".min = ");
			reduceBuf.append("prev.").append(indexId).append(".min < tempVal ? ");
			reduceBuf.append("prev.").append(indexId).append(".min : tempVal;");
			reduceBuf.append("}");
			//計算指標的平均值
			reduceBuf.append("prev.").append(indexId).append(".avg = ");
			reduceBuf.append("prev.").append(indexId).append(".sum");
			reduceBuf.append(" / ");
			reduceBuf.append("prev.").append(indexId).append(".count;");
		}
		reduceBuf.append("}");
		
		return reduceBuf.toString();
	}
	
	/**
	 * 方法描述:根據使用者選擇的指標編碼,生成MapReduce中的finalize函式
	 * @param indexMap 指標編碼
	 * @return reduce函式
	 */
	public static String generateFormulaFinalizeObject(HashMap forIdxMap, HashMap indexMap)
	{
		StringBuffer reduceBuf = new StringBuffer();
		reduceBuf.append("function(doc){");
		//得到計算指標的公式執行值
		Iterator formulaIt = forIdxMap.keySet().iterator();
		while (formulaIt.hasNext())
		{
			String indexId = (String)formulaIt.next();
			String idxFormula = (String)forIdxMap.get(indexId);
			reduceBuf.append("var tempIdx, tempFormula;");
			Iterator indexItB = indexMap.keySet().iterator();
			int i = 0;
			while (indexItB.hasNext())
			{
				String indexIdS = (String)indexItB.next();
				if(i == 0)
				{
					reduceBuf.append("tempFormula = \"").append(idxFormula).append("\";");
				}
				reduceBuf.append("tempIdx = ").append("doc.").append(indexIdS).append(".sum;");
				reduceBuf.append("tempFormula = ").append("tempFormula").append(".replace(/sum\\(").append(indexIdS).append("\\)/g,tempIdx);");
				reduceBuf.append("tempIdx = ").append("doc.").append(indexIdS).append(".count;");
				reduceBuf.append("tempFormula = ").append("tempFormula").append(".replace(/count\\(").append(indexIdS).append("\\)/g,tempIdx);");
				reduceBuf.append("tempIdx = ").append("doc.").append(indexIdS).append(".min;");
				reduceBuf.append("tempFormula = ").append("tempFormula").append(".replace(/min\\(").append(indexIdS).append("\\)/g,tempIdx);");
				reduceBuf.append("tempIdx = ").append("doc.").append(indexIdS).append(".max;");
				reduceBuf.append("tempFormula = ").append("tempFormula").append(".replace(/max\\(").append(indexIdS).append("\\)/g,tempIdx);");
				reduceBuf.append("tempIdx = ").append("doc.").append(indexIdS).append(".avg;");
				reduceBuf.append("tempFormula = ").append("tempFormula").append(".replace(/avg\\(").append(indexIdS).append("\\)/g,tempIdx);");
				i++;
			}
			reduceBuf.append("var resTemp = ").append("eval(tempFormula);");
			reduceBuf.append("doc.").append(indexId).append(" = resTemp.toFixed(2);");
		}
		
		Iterator indexItC = indexMap.keySet().iterator();
		while (indexItC.hasNext())
		{
			String indexId = (String)indexItC.next();
			reduceBuf.append("doc.").append(indexId).append(" = doc.").append(indexId).append(".self;");
		}
		reduceBuf.append("}");
		
		return reduceBuf.toString();
	}
}

注:group限制:分組後的組數不得超過20000個組!

相關推薦

javaMongodb 分組統計應用group的使用場景

------------------------場景----------------- mongodb中資料集合(ABC123)包含的指標進行統計分析,指標(指標在mongodb中實際以字母、數字組合的編碼表示)包括: A1:使用者標識、A2:使用者編碼、A3:使用者名稱稱

學以致用——Java原始碼——銷售員業績統計小程式Total Sales

程式功能: 依次輸入銷售單資料(銷售員編號、銷售產品編號、銷售金額),程式進行相應的統計。 執行結果示例: 銷售額月度彙總小程式:   請輸入0開始輸入銷售單資料(輸入-1退出):0 請輸入銷售員編號(銷售員編號範圍:1 - 4):1 請輸入產品編

Java線程面試題合集答案

call 獲取鎖 getter 監控 同步方法和同步塊 答案 協調 1.8 標記 來源:Java線程面試題 下面是我自己收集整理的Java線程相關的面試題,可以用它來好好準備面試。 參考文檔: 《Java核心技術 卷一》 Java線程面試題 To

Java執行緒面試題合集答案

下面是我自己收集整理的Java執行緒相關的面試題,可以用它來好好準備面試。 參考文件: 《Java核心技術 卷一》 Java執行緒面試題 Top 50:http://www.importnew.com/12773.html JAVA多執行緒和併發基礎面試問答: htt

[Java併發程式設計實戰] 柵欄 CyclicBarrier 實現程式碼

溫故而知新,可以為師矣。—《論語》 它的意思是:“溫習舊知識從而得知新的理解與體會,憑藉這一點就可以成為老師了 PS: 如果覺得本文有用的話,請幫忙點贊,留言評論支援一下哦,您的支援是我最大的動力!謝謝啦~ 柵欄(Barrier)類似於閉鎖,

Java TCP/IP Socket】UDP Socket程式碼

UDP的Java支援     UDP協議提供的服務不同於TCP協議的端到端服務,它是面向非連線的,屬不可靠協議,UDP套接字在使用前不需要進行連線。實際上,UDP協議只實現了兩個功能:     1)在IP協議的基礎上添加了埠;     2)對傳輸過程中可能產生的資料錯誤

mongo與javagroup by分組和排序程式碼備忘

MongoTemplate gameMt = (根據具體專案獲得)        DBCollection myColl = gameMt.getDb().getCollection("avatar");//表名         // 分組         DBObject

Java併發程式設計2執行緒中斷程式碼

使用interrupt()中斷執行緒當一個執行緒執行時,另一個執行緒可以呼叫對應的Thread物件的interrupt()方法來中斷它,該方法只是在目標執行緒中設定一個標誌,表示它已經被中斷,並立即返回。這裡需要注意的是,如果只是單純的呼叫interrupt()方法,執行緒並沒有實際被中斷,會繼續往下執行。

Java併發程式設計3執行緒掛起、恢復與終止的正確方法程式碼

JAVA大資料中高階架構 2018-11-06 14:24:56掛起和恢復執行緒Thread 的API中包含兩個被淘汰的方法,它們用於臨時掛起和重啟某個執行緒,這些方法已經被淘汰,因為它們是不安全的,不穩定的。如果在不合適的時候掛起執行緒(比如,鎖定共享資源時),此時便可能會發生死鎖條件——其他執行緒在等待該

Java併發程式設計8多執行緒環境中安全使用集合API程式碼

Java併發程式設計(8):多執行緒環境中安全使用集合API(含程式碼)JAVA大資料中高階架構 2018-11-09 14:44:47在集合API中,最初設計的Vector和Hashtable是多執行緒安全的。例如:對於Vector來說,用來新增和刪除元素的方法是同步的。如果只有一個執行緒與Vector的例

Java併發程式設計9死鎖程式碼

JAVA大資料中高階架構 2018-11-10 14:04:32當執行緒需要同時持有多個鎖時,有可能產生死鎖。考慮如下情形: 執行緒A當前持有互斥所鎖lock1,執行緒B當前持有互斥鎖lock2。接下來,當執行緒A仍然持有lock1時,它試圖獲取lock2,因為執行緒B正持有lock2,因此執行緒A會阻塞等

JAVAExcel匯入匯出詳解3--匯出

Excel匯出 一、設定查詢條件 注意:無法通過Ajax下載 jsp程式碼 <form class="col-sm-2" action="/manage/order/download" method="post" onsubmit="checkForm()"

JAVAExcel匯入匯出詳解2--匯入

1. 瀏覽資料夾,選擇需要上傳的檔案 程式碼 jsp <li class="col-sm-1"> <span>上&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&a

mongodb分組統計,並且刪除重複資料

// 找出按pipe_id過濾重複的資料展示出來,第一個match是查詢條件,$group是分組條件,後一個match是count>1的才展示出來,allowDiskUse:true允許到硬碟操作  db.flow_data.aggregate([{ $match: {

java執行緒池任務提交Runnable、Callable、FutureTask

任務的封裝與執行過程 (注:下面所說的Runnable物件,Callable物件都是指實現了該介面的類的物件) 之前要交給執行緒執行的任務我們都把它封裝在Runnable中。對於執行緒池而言,多了一種Callable的封裝方式。 Runnable:其中的run()方法沒有返回值。

《網際網路程式設計Java》——課程筆記7UDP套接字程式設計無連線

學會使用UDP套接字來實現網路應用程式設計。 UDP通訊特點:     (1) UDP有別於TCP,有自己獨立的套接字(IP+PORT),它們的埠號不衝突;     (2) UDP 通訊前通常[不]需要連線;     (3) 基於使用者資料報文(包)讀寫;    

Java併發程式設計】之二十併發新特性—Lock鎖和條件變數程式碼

簡單使用Lock鎖     Java 5中引入了新的鎖機制——java.util.concurrent.locks中的顯式的互斥鎖:Lock介面,它提供了比synchronized更加廣泛的鎖定操作。Lock介面有3個實現它的類:ReentrantLock、Reetrant

javaMongoDB的簡單應用例項

1 首先載入 MongoDB的jar包。下載Jar包連結 2然後進行相應的配置。如我當前專案是在web-pom.xml 的的節點下配置。 <dependency> <groupId>org.mo

MongoDB分組統計的一個例子

這幾天被MongoDB整瘋了。 算是對MongoDB有了進一步的瞭解,還是有很多坑等著去探索。 一個是關於MongoDB中Int64 Int32 Double三個資料型別,PHP中只有int型,那麼3

應用程式框架實戰十二公共操作類開發技巧初學者必讀

  本文專門為初學者而寫,因為很多初學者可能還不瞭解公共操作類的作用和封裝技巧,大部分有經驗的程式設計師都會把自己所碰到的技術問題整理封裝成類,這就是公共操作類。公共操作類往往具有一些通用性,也可能專門解決某些棘手問題。公共操作類是應用程式框架的核心,主要目標是解決大部分技術問題。我將在本文介紹封裝公共操作類