本實驗主要包含三部分:
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方法中注釋掉就好了,用雙斜杠//注釋即可。
一改以往的作風,這次稍稍的封裝了下,誰叫咱是喜歡面向對象的碼農呢。。。