網站使用者行為資料統計與分析之二:資料寫入mongodb
阿新 • • 發佈:2018-12-24
接著上一篇博文,我再補充一下:
在js中收集到使用者行為資料之後呢,我們要在後臺對資料進行處理,怎麼處理?在實際專案中我分兩條路走:
一、直接寫入mongodb,隨著電商網站規模越來越大,訪問量越來越高,這種非關係型資料庫可以有效地化解高併發的問題
二、做日誌處理(後臺資料-----redis-----logstash-----elasticsearch------kibana)
在這篇文章中,我們先來探討寫DB。
兩種方式,一、利用java mongodb api;二、利用log4j
方式一mongodb提供了很友好的java api
我們先來看看:
以上程式碼,CRUD好像都有了!但是有個問題需要指出,mongodb有預設的連線池,只不過預設連線數為10,我們如果有特別需要,可以自建連線池package com.founder.ec.util; import java.net.SocketException; import java.net.UnknownHostException; import com.founder.ec.entity.BehaviorUser; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.Mongo; /** * 實現MongoDB的CRUD操作 * * @author 五味子 * @version 2014/04/04 */ public class MongOpera { private static DB db; private static DBCollection users; private static Mongo mg; @SuppressWarnings("deprecation") public static DBCollection init() { try { try { mg = DBManager.inits("192.168.2.87", 27017, 300); } catch (SocketException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 獲取temp DB;如果預設沒有建立,mongodb會自動建立 db = mg.getDB("test"); // 獲取users DBCollection;如果預設沒有建立,mongodb會自動建立 users = db.getCollection("testdb"); return users; } /**//** * 銷燬mongo物件 * @param * @return *//* public static void destory() { if (mg != null) mg.close(); mg = null; db = null; users = null; System.gc();//記憶體垃圾回收 } *//** * 列印查詢結果 * @param o * @return *//* public static void print(Object o) { System.out.println(o); } *//** * 查詢所有資料 * @param * @return *//* private static void queryAll() { print("查詢users的所有資料:"); // db遊標 DBCursor cur = users.find(); while (cur.hasNext()) { print(cur.next()); } }*/ /** * 新增資料 * @param Synchronized * @param * @return */ public static void add(BehaviorUser behaviorUser) { // 先查詢所有資料 //queryAll(); //print("count: " + users.count()); DBObject user = new BasicDBObject(); user.put("sessionId", behaviorUser.getSessionId()); user.put("uuid", 24); user.put("memberId", behaviorUser.getMemberId()); user.put("refPage", behaviorUser.getRefPage()); user.put("firstPage", behaviorUser.getFirstPage()); user.put("initTime", behaviorUser.getInitTime()); user.put("orderId", behaviorUser.getOrderId()); user.put("currentTime", behaviorUser.getCurrentTime()); user.put("currentURL", behaviorUser.getCurrentPage()); users = init(); users.save(user);//儲存,getN()獲取影響行數 /*List list1 = new ArrayList(); List<DBObject> list2 = null; list1.add(user); if (list1.size()>=30) { list2 = new ArrayList(); Synchronized{ list2.addAll(list1); list1.clear(); } new Thread().start(); new Thread( try{ users.insert(list2); }catch(ApplicationException e){ } ).start(); }*/ //print(users.save(user).getN()); /*// 擴充套件欄位,隨意新增欄位,不影響現有資料 user.put("sex", "男"); print(users.save(user).getN()); // 新增多條資料,傳遞Array物件 print(users.insert(user, new BasicDBObject("name", "tom")).getN()); // 新增List集合 List<DBObject> list = new ArrayList<DBObject>(); list.add(user); DBObject user2 = new BasicDBObject("name", "lucy"); user.put("age", 22); list.add(user2); // 新增List集合 print(users.insert(list).getN()); // 查詢下資料,看看是否新增成功 print("count: " + users.count()); queryAll();*/ } /* *//** * 移除資料 * @param * @return *//* public static void remove() { queryAll(); print("刪除id = 4de73f7acd812d61b4626a77:" + users.remove( new BasicDBObject("_id", new ObjectId( "4de73f7acd812d61b4626a77"))).getN()); print("remove age >= 24: " + users.remove( new BasicDBObject("age", new BasicDBObject("$gte", 24))) .getN()); } *//** * 修改資料 * @param * @return *//* public static void modify() { print("修改:" + users.update( new BasicDBObject("_id", new ObjectId( "4dde25d06be7c53ffbd70906")), new BasicDBObject("age", 99)).getN()); print("修改:" + users.update( new BasicDBObject("_id", new ObjectId( "4dde2b06feb038463ff09042")), new BasicDBObject("age", 121), true,// 如果資料庫不存在,是否新增 false// 多條修改 ).getN()); print("修改:" + users.update(new BasicDBObject("name", "haha"), new BasicDBObject("name", "dingding"), true,// 如果資料庫不存在,是否新增 true// false只修改第一天,true如果有多條就不修改 ).getN()); // 當資料庫不存在就不修改、不新增資料,當多條資料就不修改 // print("修改多條:" + coll.updateMulti(new BasicDBObject("_id", new // ObjectId("4dde23616be7c19df07db42c")), new BasicDBObject("name", // "199"))); } *//** * 條件查詢 * @param * @return *//* public static void query() { // 查詢所有 // queryAll(); // 查詢id = 4de73f7acd812d61b4626a77 print("find id = 4de73f7acd812d61b4626a77: " + users.find( new BasicDBObject("_id", new ObjectId( "4de73f7acd812d61b4626a77"))).toArray()); // 查詢age = 24 print("find age = 24: " + users.find(new BasicDBObject("age", 24)).toArray()); // 查詢age >= 24 print("find age >= 24: " + users.find( new BasicDBObject("age", new BasicDBObject("$gte", 24))) .toArray()); print("find age <= 24: " + users.find( new BasicDBObject("age", new BasicDBObject("$lte", 24))) .toArray()); print("查詢age!=25:" + users.find( new BasicDBObject("age", new BasicDBObject("$ne", 25))) .toArray()); print("查詢age in 25/26/27:" + users.find( new BasicDBObject("age", new BasicDBObject( QueryOperators.IN, new int[] { 25, 26, 27 }))) .toArray()); print("查詢age not in 25/26/27:" + users.find( new BasicDBObject("age", new BasicDBObject( QueryOperators.NIN, new int[] { 25, 26, 27 }))) .toArray()); print("查詢age exists 排序:" + users.find( new BasicDBObject("age", new BasicDBObject( QueryOperators.EXISTS, true))).toArray()); print("只查詢age屬性:" + users.find(null, new BasicDBObject("age", true)).toArray()); // 只查詢一條資料,多條去第一條 print("findOne: " + users.findOne()); print("findOne: " + users.findOne(new BasicDBObject("age", 26))); print("findOne: " + users.findOne(new BasicDBObject("age", 26), new BasicDBObject("name", true))); // 查詢修改、刪除 print("findAndRemove 查詢age=25的資料,並且刪除: " + users.findAndRemove(new BasicDBObject("age", 25))); // 查詢age=26的資料,並且修改name的值為Abc print("findAndModify: " + users.findAndModify(new BasicDBObject("age", 26), new BasicDBObject("name", "Abc"))); print("findAndModify: " + users.findAndModify(new BasicDBObject("age", 28), // 查詢age=28的資料 new BasicDBObject("name", true), // 查詢name屬性 new BasicDBObject("age", true), // 按照age排序 false, // 是否刪除,true表示刪除 new BasicDBObject("name", "Abc"), // 修改的值,將name修改成Abc true, true)); queryAll(); } *//** * mongoDB不支援聯合查詢、子查詢,這需要我們自己在程式中完成。將查詢的結果集在Java查詢中進行需要的過濾即可。 * @param * @return *//* public static void testOthers() { DBObject user = new BasicDBObject(); user.put("name", "hoojo"); user.put("age", 24); // JSON 物件轉換 print("serialize: " + JSON.serialize(user)); // 反序列化 print("parse: " + JSON.parse("{ \"name\" : \"hoojo\" , \"age\" : 24}")); print("判斷temp Collection是否存在: " + db.collectionExists("temp")); // 如果不存在就建立 if (!db.collectionExists("temp")) { DBObject options = new BasicDBObject(); options.put("size", 20); options.put("capped", 20); options.put("max", 20); print(db.createCollection("account", options)); } // 設定db為只讀 db.setReadOnly(true); // 只讀不能寫入資料 db.getCollection("test").save(user); }*/ }
package com.founder.ec.util; import com.mongodb.Mongo; import com.mongodb.MongoOptions; /** * mongodb連線池 * @author 五味子 * @version 2014/04/04 */ public class DBManager{ private static Mongo mongo; //mongodb資料庫操作物件 /** * * @param ip ip地址 * @param port 埠號 * @param poolSize 連線數 * @return Mongo操作物件 * @throws java.net.UnknownHostException 找不到主機異常 */ public static Mongo inits(final String ip, int port, int poolSize) throws java.net.UnknownHostException,java.net.SocketException { try{ System.setProperty("MONGO.POOLSIZE", String.valueOf(poolSize)); if (mongo == null) { mongo = new Mongo(ip, port); MongoOptions options = mongo.getMongoOptions(); //每個主機的連線數 options.connectionsPerHost = poolSize; //這個控制是否在一個連線時,系統會自動重試 options.autoConnectRetry = true; //最大等待連線的執行緒阻塞時間 options.maxWaitTime = 5000; //socket超時。0是預設和無限 options.socketTimeout = 2000; //連線超時的毫秒。0是預設和無限 options.connectTimeout = 15000; //執行緒佇列數,它以上面connectionsPerHost值相乘的結果就是執行緒佇列最大值。如果連線執行緒排滿了佇列就會丟擲“Out of semaphores to get db”錯誤。 options.threadsAllowedToBlockForConnectionMultiplier = 4; } }catch(Exception e){ e.getMessage(); } return mongo; } }
方式二:log4j
這種方式比較簡單,只不過只能作為新增資料用
在log4j.propertites檔案中:
log4j.rootLogger=debug, stdout, R, MongoDB
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{MM-dd HH:mm:ss.SSS} %-5p - [%c{1}.%t] %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=D:/data/Sample.log
log4j.appender.R.MaxFileSize=1000KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%-d{MM-dd HH:mm:ss.SSS} %-5p - [%c{1}.%t] %m%n
#log4j.appender.MongoDB=org.log4mongo.MongoDbAppender
#log4j.appender.MongoDB.databaseName=test
#log4j.appender.MongoDB.collectionName=testdb
#log4j.appender.MongoDB.hostname=192.168.2.86
#log4j.appender.MongoDB.port=27017
注意打上#的幾段程式碼,應該不要解釋吧!
什麼?你看不懂屬性檔案,那你還是先補補屬性檔案再來看吧!
想進一步瞭解Mongodb,請閱讀超詳細的中文指南:
http://download.csdn.net/detail/u013339851/7120473