基于Java對(duì)于MongoDB數(shù)據(jù)庫(kù)的復(fù)雜查詢操作

前言

在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的名字>");
      
    至此,我們已經(jīng)可以連接到MongoDB下的所有數(shù)據(jù)表格,下面就可以來(lái)看看基于java對(duì)于MongoDB的復(fù)雜語(yǔ)句操作了。

基于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)基本涵蓋,希望可以幫助到各位。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,626評(píng)論 18 399
  • 這部分主要是開(kāi)源Java EE框架方面的內(nèi)容,包括Hibernate、MyBatis、Spring、Spring ...
    雜貨鋪老板閱讀 1,554評(píng)論 0 2
  • 第一次使用簡(jiǎn)書 希望大家以后多多指教 喜歡的兩個(gè)球星,附上一張我科的圖片 我科 附上我黑格林的圖(有多少人討厭就有...
    BWWWWB閱讀 239評(píng)論 3 0
  • 公元前一百七十年,匈奴單于率十萬(wàn)大軍犯吾邊境,玉門關(guān)告急。漢文帝發(fā)檄文征告天下,一時(shí)間風(fēng)云際會(huì),英雄輩出,群龍嘯聚...
    范三石閱讀 4,555評(píng)論 0 1
  • 致親愛(ài)的快樂(lè)狗耳山戶外群的伙伴們: 在這秋高氣爽,收獲豐收的美好季節(jié),我們迎來(lái)了快樂(lè)狗耳山戶外群成立一周年的喜慶日...
    朱金玲閱讀 338評(píng)論 0 0

友情鏈接更多精彩內(nèi)容