前言
在sql轉(zhuǎn)noSql途中總是免不了一些對(duì)于原有的復(fù)雜sql語(yǔ)句的轉(zhuǎn)譯工作,因?yàn)椴皇煜ava環(huán)境下對(duì)于mongoDB操作的語(yǔ)句,所以走了不少的彎路,這些復(fù)雜語(yǔ)句在stackoverflow中找又會(huì)花上不少時(shí)間,于是在這里做個(gè)記錄。
Java的配置并且連接MongoDB
- 首先在pom.xml文件中加入依賴包: "mongo-java-driver"(因?yàn)閟cala對(duì)于java的支持,所以這個(gè)driver就不作區(qū)分了),配置的代碼如下:
<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.4.2</version> </dependency> - 連接Mongo Server以及collection的方法
- org.mongodb中提供了ServerAddress類用來(lái)儲(chǔ)存連接mongo的ip地址以及端口,初始化的方法為:
private ServerAddress serverAddress = new ServerAddress("<ip地址>", "<端口>(這是個(gè)int)"); - 如果這個(gè)MongoDB的服務(wù)器是一個(gè)集群,那么通常來(lái)說(shuō)需要設(shè)置setSlaveOK才能通過(guò)某一臺(tái)服務(wù)器去訪問(wèn)數(shù)據(jù),但是,我們可以把整個(gè)集群的服務(wù)器list輸入給ServerAddress類,其初始化的方法為:
private MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("<ip地址1>", "<端口>(這是個(gè)int)"), new ServerAddress("<ip地址2>", "<端口>(這是個(gè)int)"), new ServerAddress("<ip地址3>", "<端口>(這是個(gè)int)"))); - 如果這個(gè)mongoDB的數(shù)據(jù)庫(kù)是有權(quán)限訪問(wèn)設(shè)置的數(shù)據(jù)庫(kù),則還需要MongoCredential類將數(shù)據(jù)庫(kù)的 名稱,用戶名,密碼傳入連接數(shù)據(jù)庫(kù)的方法中,其初始化的方法為:
private MongoCredential credential = MongoCredential.createCredential("<用戶名>", "<數(shù)據(jù)庫(kù)名稱>", "<密碼>"); - 最后才是連接MongoDB數(shù)據(jù)庫(kù)的操作,使用的是MongoClient類,其初始化的方法為:(注意這里的credential變量需要轉(zhuǎn)化為L(zhǎng)ist類才能作為輸入)
private MongoClient mongoClient = new MongoClient(serverAddress, Arrays.asList(credential)); - 如若要獲取這個(gè)server下的某一個(gè)數(shù)據(jù)庫(kù)(Database),則需要執(zhí)行如下方法:
MongoDatabase mydb = mongoClient.getDatabase("<數(shù)據(jù)庫(kù)名稱>"); - 在mongoDB中,我們熟知的table被稱為collection,所以如果要獲得某個(gè)collection(表格),需要執(zhí)行如下的方法:
MongoCollection myCollection = mydb.getCollection("<該數(shù)據(jù)庫(kù)下collection的名字>");
- org.mongodb中提供了ServerAddress類用來(lái)儲(chǔ)存連接mongo的ip地址以及端口,初始化的方法為:
基于Java對(duì)于MongoDB數(shù)據(jù)庫(kù)的復(fù)雜語(yǔ)句查詢
- 基礎(chǔ)準(zhǔn)備
- 在對(duì)MongoDB執(zhí)行復(fù)雜查詢之前,我們先要了解一下在Mongo-Java-Driver中是如何儲(chǔ)存查詢結(jié)果的。其用于儲(chǔ)存結(jié)果的類是MongoCursor, 其通過(guò)collection類的find方法獲取查詢結(jié)果并通過(guò).iterator()方法返回該MongoCursor類,本質(zhì)是一個(gè)類似于Iterator的對(duì)象,可以通過(guò)調(diào)用hasNext()與next()方法來(lái)遍歷整個(gè)返回結(jié)果。
- 另一方面,MongoCursor中所儲(chǔ)存的數(shù)據(jù)類型為Document,類似于Json的存儲(chǔ)方式,可以通過(guò)google的Gson包將其映射為你想要的java對(duì)象,實(shí)現(xiàn)方式為:
private Gson gson = new Gson(); // 轉(zhuǎn)換為對(duì)象 gson.fromJson(gson.toJson(<你所獲得的Document對(duì)象>), <你需要轉(zhuǎn)換的成為的對(duì)象>.class)
- Java對(duì)MongoDB的復(fù)雜語(yǔ)句查詢操作
這里為了保證對(duì)sql選手親和度(我本人也是從sql起步的),我會(huì)盡量把這里的一些查詢翻譯成sql中比較相似的操作。-
where分句
-
常用的判別符號(hào)
基于Java的MongoDB的查詢語(yǔ)句如果需要指定where的條件,需要用到BasicDBObject類用于存儲(chǔ)where分句中判別字段(列的名稱),判別類型(等于,不等于,大于,小于)和用于判別的值。其基本的初始化方法為:BasicDBObject dbObject = new BasicDBObject("<判別類型>", "用于判別的值"); // 指定判別的字段 BasicDBObject identification = new BasicDBObject("<用于判別的字段(列的名字)>", dbObject) // Example: 取得大于等于某個(gè)時(shí)間點(diǎn)的所有數(shù)據(jù)庫(kù)記錄 BasicDBObject exObject = new BasicDBObject("time", new BasicDBObject("$gte", (from + " 00:00")))常用判別符號(hào)有:
判別符號(hào) 意義 $eq 相等 $ne 不等于 $gte 大于等于 $gt 大于 $lte 小于等于 $lt 小于 -
在where分句中使用and和or等邏輯關(guān)聯(lián)詞
從上面的敘述中可以看到,我們可以用BasicDBObject對(duì)象來(lái)表示對(duì)某個(gè)字段(某列)做限制條件的查找。如果要將這些查詢條件使用邏輯關(guān)聯(lián)詞連在一起,則我們需要使用List對(duì)象將這些要關(guān)聯(lián)的條件語(yǔ)句(BasicDBObject對(duì)象)連接在一起,再在最外層用一個(gè)新的BasicDBObject對(duì)象封裝這些用邏輯連詞連在一起的BasicDBObject List。具體實(shí)現(xiàn)代碼如下:// 使用List來(lái)連接需要用邏輯關(guān)聯(lián)詞串聯(lián)起來(lái)的條件語(yǔ)句 List<DBObject> criteria = new ArrayList<>(); criteria.add(new BasicDBObject("time", new BasicDBObject("$gte", (from + " 00:00")))); criteria.add(new BasicDBObject("time", new BasicDBObject("$lte", (to + " 23:59")))); criteria.add(new BasicDBObject("idc_group", idcGroup)); // 使用and來(lái)連接這個(gè)list // 這里也可以使用"$or"字段表示"或"邏輯 BasicObject andConnection =new BasicDBObject("$and", criteria); // 之后使用find方法去找到符合這個(gè)where條件的記錄。 MongoCursor<Document> tCursor = mydb.getCollection(table).find(new BasicDBObject("$and", criteria)).iterator();
-
-
聚合操作(Aggregation, Group By)
基于Java對(duì)于MongoDB數(shù)據(jù)庫(kù)查詢?nèi)绻枰獔?zhí)行聚合操作,則需要從MongoCollection對(duì)象調(diào)用aggregate方法,并把所需要的條件串聯(lián)為list并作為輸入進(jìn)入aggregate方法。常用的一些關(guān)鍵詞有:關(guān)鍵詞 意義 $match 相等,類似于where中的等于某值 $sort 排序 $limit 與mysql中的limit相同 具體的關(guān)鍵詞操作請(qǐng)參照文檔 http://www.runoob.com/mongodb/mongodb-aggregate.html
下面給出例子:// 目標(biāo):獲取所有滿足如下條件的數(shù)據(jù): // 1. "date"字段滿足某個(gè)值 // 2. 先通過(guò)orderName1降序,再通過(guò)orderName2降序 // 3. 獲取的記錄不超過(guò)10條 MongoCursor<Document> cursor = quality.aggregate(Arrays.asList( // "$match"用于篩選date匹配這個(gè)值的記錄 new Document("$match", new Document("date", (int)(Integer.valueOf(timeInput[0] + timeInput[1] + timeInput[2])))), new BasicDBObject("$sort", new BasicDBObject(orderName1, -1)), new BasicDBObject("$sort", new BasicDBObject(orderName2, -1)), new BasicDBObject("$limit", 10) )).iterator(); 值得一提的是,因?yàn)镸ongoDB自身數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)方式的問(wèn)題,其不支持對(duì)于兩個(gè)collection進(jìn)行join的操作。
-
至此,基于Java對(duì)MongoDB數(shù)據(jù)庫(kù)的查詢的復(fù)雜操作已經(jīng)基本涵蓋,希望可以幫助到各位。