[原創(chuàng)] Java實現MongoDB數據導入及自定義復雜查詢函數

本實驗主要包含三部分:

1、從源文件中加載數據至數據庫中。

2、從數據庫中查詢數據驗證加載是否完成。

3、自定義特定的查詢函數。

這么看,Java也是支持Mongo中的原生語法,不賴!對比Python來說,代碼量稍多了些,

畢竟一個是弱類型、非防御式編程,一個是強類型、防御式編程,Java畢竟不擅長用來編寫腳本。

測試數據:

wubiao,chinese,91

wubiao,math,11

zhangsan,english,40

zhangsan,politics,95

zhangsan,physics,84

lisi,computer,92

lisi,english,95

lisi,chinese,88

wanger,mathematics,90

wanger,english,60

wanger,chinese,40

zhaoliu,economics,96

zhaoliu,computer,94

復制代碼

計劃數據庫中存儲數據結構為:

{ "course" : "chinese", "score" : 91, "name" : "wubiao" }

{ "course" : "math", "score" : 11, "name" : "wubiao" }

{ "course" : "english", "score" : 40, "name" : "zhangsan" }

{ "course" : "politics", "score" : 95, "name" : "zhangsan" }

{ "course" : "physics", "score" : 84, "name" : "zhangsan" }

{ "course" : "computer", "score" : 92, "name" : "lisi" }

{ "course" : "english", "score" : 95, "name" : "lisi" }

{ "course" : "chinese", "score" : 88, "name" : "lisi" }

{ "course" : "mathematics", "score" : 90, "name" : "wanger" }

{ "course" : "english", "score" : 60, "name" : "wanger" }

{ "course" : "chinese", "score" : 40, "name" : "wanger" }

{ "course" : "economics", "score" : 96, "name" : "zhaoliu" }

{ "course" : "computer", "score" : 94, "name" : "zhaoliu" }

復制代碼

源文件每行數據包含姓名、課程、得分,以逗號分隔。對于這幾條數據來說,完全可以用Mongo客戶端手段插入,

但是如果幾十萬條,幾百萬條呢?不可能一行一行自己插,所以必須要借助工具或腳本實現。

本次查找的需求是:找出有至少兩門課程成績達到90以上的學員名單。這只是個很簡單的需求,其實我們完全可以很輕松的自定義各種復雜的查詢函數。

環(huán)境:

OS:CentOS 5.9 32bit

JDK:jdk1.6.0_29

MongoDB: 2.2.3

driver:mongo-2.10.1.jar

如果MongoDB還沒安裝配置好,可以參考:

CentOS下使用yum安裝MongoDB及相關配置http://f.dataguru.cn/forum.php?mod=viewthread&tid=56377&fromuid=4771

如果不了解MongoDB的java驅動可以參考:

JAVA操作MongoDB--mongodb/mongo-java-driver

http://f.dataguru.cn/forum.php?mod=viewthread&tid=94472&fromuid=4771

OK,開搞。。

先啟動mongod

[root@biao ~]# mongod -f /etc/mongod.conf

all output going to: /mongodb/log/mongodb.log

forked process: 32465

child process started successfully, parent exiting

[root@biao ~]# service mongod status

mongod (pid 32465) is running...

[root@biao ~]# ps aux|grep mongod

root? ???32465??0.6??0.7 118388 22008 ?? ?? ???Sl? ?02:00? ?0:00 mongod -f /etc/mongod.conf

root? ???32559??0.0??0.0? ?4032? ?684 pts/11? ?R+? ?02:01? ?0:00 grep mongod

[root@biao ~]# netstat -aux|grep mongod

unix??2? ?? ?[ ACC ]? ???STREAM? ???LISTENING? ???519024 /tmp/mongodb-27017.sock

復制代碼

如上所示,mongod啟動成功,監(jiān)聽端口為27017。

Java代碼:

package com.wubiao.mongo;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.net.UnknownHostException;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import com.mongodb.BasicDBObject;

import com.mongodb.DB;

import com.mongodb.DBCollection;

import com.mongodb.DBCursor;

import com.mongodb.DBObject;

import com.mongodb.MongoClient;

public class Test {

public static void main(String[] args) {

Test test = new Test();

DBCollection dbCollection = null;

try {

dbCollection = test.getCollection(null, "test_java", "stu");

} catch (UnknownHostException e) {

e.printStackTrace();

}

// 源文件路徑為/root/Desktop/data.txt

String separator = File.separator;

File file = new File(separator + "root" + separator + "Desktop" + separator + "data.txt");

//加載數據,并返回成功加載的行數

test.loadData(file, dbCollection);

//打印所有文檔

test.printAllDocs(dbCollection);

//查找至少兩門課成績達到90以上的同學名單

test.findNameByTwoScore(dbCollection);

}

/**

* 獲取要操作的集合

* @param mongoClient

* @param database

* @param collection

* @return

* @throws UnknownHostException

*/

public DBCollection getCollection(MongoClient mongoClient, String database, String collection) throws UnknownHostException {

if (mongoClient == null) {

//建立連接

mongoClient = new MongoClient();

}

//獲取數據庫

DB db = mongoClient.getDB(database);

//獲取集合

DBCollection dbCollection = db.getCollection(collection);

return dbCollection;

}

/**

* 從源文件中加載數據至數據庫中

* @param file 源數據文件

* @param dbCollection 要加載至的集合

* @return 返回成功加載的行數,也就是文檔數

*/

public int loadData(File file,DBCollection dbCollection) {

if (file == null || !file.isFile() || !file.exists()) {

return 0;

}

BufferedReader reader = null;

ArrayList docs = new ArrayList();

try {

reader = new BufferedReader(new FileReader(file));

String line = null;

System.out.println("***下列行將會作為文檔被插入至數據庫中...***");

while ((line = reader.readLine()) != null) {

System.out.println(line);

String[] lines = line.split(",");

BasicDBObject doc = new BasicDBObject();

doc.append("name", lines[0]);

doc.append("course", lines[1]);

doc.append("score", Integer.valueOf(lines[2]));

docs.add(doc);

}

if (docs.size() > 0) {

dbCollection.insert(docs);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

if (reader != null) {

try {

reader.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

System.out.println("***總計有" + docs.size() + "行作為文檔已被插入數據庫中...***");

return docs.size();

}

/**

* 打印集合中包含的所有文檔

* @param dbCollection 要查詢的集合

*/

public static void printAllDocs(DBCollection dbCollection) {

//獲取當前集合中所有對象的游標

DBCursor dbCursor = dbCollection.find();

//迭代打印所有對象

System.out.println("****當前集合包含的所有文檔 begin****");

while (dbCursor.hasNext()) {

System.out.println("* " + dbCursor.next());

}

System.out.println("****當前集合包含的所有文檔 end******");

}

/**

* 在集合中查詢至少兩門課程成績大于90的學員

* @param dbCollection 要查詢的集合

* @return 查詢符合條件的學員姓名

*/

public List findNameByTwoScore(DBCollection dbCollection) {

//獲取所有學員的姓名

ArrayList AllNames = (ArrayList) dbCollection.distinct("name");

//要返回的學員姓名列表

ArrayList names = new ArrayList();

//迭代學員姓名,按學員姓名與成績大于90作為查詢條件

//當查詢所得的結果大于等于2時,表示符合查詢,返回

for (Iterator iter = AllNames.iterator(); iter.hasNext(); ) {

String name = iter.next();

DBCursor cursor = dbCollection.find(new BasicDBObject("name",name).append("score", new BasicDBObject("$gt",90)));

if (cursor.count() > 1) {

names.add(name);

}

}

System.out.println("***至少兩門課成績達到90以上的同學名單:");

System.out.println(names);

return names;

}

}

/*

控制臺打印信息:

***下列行將會作為文檔被插入至數據庫中...***

wubiao,chinese,91

wubiao,math,11

zhangsan,english,40

zhangsan,politics,95

zhangsan,physics,84

lisi,computer,92

lisi,english,95

lisi,chinese,88

wanger,mathematics,90

wanger,english,60

wanger,chinese,40

zhaoliu,economics,96

zhaoliu,computer,94

***總計有13行作為文檔已被插入數據庫中...***

****當前集合包含的所有文檔 begin****

* { "_id" : { "$oid" : "5167513de4b0619e77863b43"} , "name" : "wubiao" , "course" : "chinese" , "score" : 91}

* { "_id" : { "$oid" : "5167513de4b0619e77863b44"} , "name" : "wubiao" , "course" : "math" , "score" : 11}

* { "_id" : { "$oid" : "5167513de4b0619e77863b45"} , "name" : "zhangsan" , "course" : "english" , "score" : 40}

* { "_id" : { "$oid" : "5167513de4b0619e77863b46"} , "name" : "zhangsan" , "course" : "politics" , "score" : 95}

* { "_id" : { "$oid" : "5167513de4b0619e77863b47"} , "name" : "zhangsan" , "course" : "physics" , "score" : 84}

* { "_id" : { "$oid" : "5167513de4b0619e77863b48"} , "name" : "lisi" , "course" : "computer" , "score" : 92}

* { "_id" : { "$oid" : "5167513de4b0619e77863b49"} , "name" : "lisi" , "course" : "english" , "score" : 95}

* { "_id" : { "$oid" : "5167513de4b0619e77863b4a"} , "name" : "lisi" , "course" : "chinese" , "score" : 88}

* { "_id" : { "$oid" : "5167513de4b0619e77863b4b"} , "name" : "wanger" , "course" : "mathematics" , "score" : 90}

* { "_id" : { "$oid" : "5167513de4b0619e77863b4c"} , "name" : "wanger" , "course" : "english" , "score" : 60}

* { "_id" : { "$oid" : "5167513de4b0619e77863b4d"} , "name" : "wanger" , "course" : "chinese" , "score" : 40}

* { "_id" : { "$oid" : "5167513de4b0619e77863b4e"} , "name" : "zhaoliu" , "course" : "economics" , "score" : 96}

* { "_id" : { "$oid" : "5167513de4b0619e77863b4f"} , "name" : "zhaoliu" , "course" : "computer" , "score" : 94}

****當前集合包含的所有文檔 end******

***至少兩門課成績達到90以上的同學名單:

[lisi, zhaoliu]

*/

復制代碼

依然照顧到有些童鞋可能不太熟悉Java,依然嘗試著在代碼中加入了很詳細的注釋,依然應該很詳細了。

代碼除了連接、獲取數據庫、獲取集合之外,包含三部分:

1、從源文件中加載數據至數據庫中。

2、查詢所有的文檔驗證導入的數據。

3、實現自定義查詢。

這三部分是相對獨立的,分別有Test類中的三個方法實現,具體哪個方法執(zhí)行哪些工作不用解釋了,方法名就看得出來。

三個方法可以一起執(zhí)行,也可以分別執(zhí)行,不想執(zhí)行的部分在main方法中注釋掉就好了,用雙斜杠//注釋即可。

一改以往的作風,這次稍稍的封裝了下,誰叫咱是喜歡面向對象的碼農呢。。。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容