1. 程式人生 > >SpringBoot整合MongoDB,使用mongoTemplate實現高階查詢

SpringBoot整合MongoDB,使用mongoTemplate實現高階查詢

一、前言

最近專案使用MongoDB作為資料主要存取的地方

又是第一次接觸MongoDB,也是踩了不少坑...

維護資料無非就是增刪改查,而裡面最複雜的就是查詢了

所以來總結一下有關MongoDB的查詢方法

當然如果你在此之前你對MongoDB一點都不瞭解的話

個人建議點選這裡,花三十分鐘初步瞭解一下MongoDB

ok,正文開始

二、正文

1.使用mongoTemplate物件常常會呼叫如下兩種方法

① 

          分析:此方法入兩個引數,前者entityClass是類型別 即某個實體類,後者collectionName是String型別

                     即MongoDB的某個集合名,那麼這個方法很明顯就是根據入參的集合名稱到MongoDB中查詢並

                     轉換為指定的類型別。

   注:entityClass引數的寫法應為 xxx.class ,如Student學生類:Student.class

分析:此方法三個引數,與①不同的是,多了第一個query引數,這個query就是用來封裝查詢條件的

2.Query的使用(這裡以我自己的一個業務邏輯角度寫的,下面有這個邏輯的連貫程式碼)

① 首先在這個方法裡面需要定義如下兩個物件

//用來封裝所有條件的物件
Query query = new Query();
//用來構建條件
Criteria criteria = new Criteria();

② 先來一個模糊查詢的條件

/**
  * 這裡使用的正則表示式的方式
  * 第二個引數Pattern.CASE_INSENSITIVE是對字元大小寫不明感匹配
  */
Pattern pattern = Pattern.compile("^.*"+這裡拼接你的查詢條件字串+".*$", Pattern.CASE_INSENSITIVE);
/**
  *  criteria.and().regex() 在這裡是構建了一個模糊查詢的條件,並且用 'and' 相連
  *  query.addCriteria 把條件封裝起來
  */
query.addCriteria(criteria.and("這裡填寫你MongoDB集合中的key").regex(pattern));

③ 再來一個精準查詢的條件

/**
  *  criteria.and().is() 在這裡是構建了一個精準查詢的條件,並且用 'and' 相連
  *  query.addCriteria 把條件封裝起來
  */
query.addCriteria(criteria.and("你MongoDB中的key").is("你的條件");

④ 來一個在某個值之間的條件(類似於sql中的BETWEEN ... AND

如果在這裡,模仿精準查詢,把 is() 方法換成 gt() 或 lt() ,然後執行,肯定會報錯,具體的

錯誤資訊我沒有記錄下來,大概意思就是同一個欄位連續出現了兩次

這裡需要用到 andOperator 方法,如下

//大於方法
Criteria gt = Criteria.where("你MongoDB中的key").gt("你的條件");
//小於方法
Criteria lt = Criteria.where("你MongoDB中的key").lt("你的條件");
/**
  * new Criteria().andOperator(gt,lt) 把上面的大於和小於放在一起,注意上面兩個key一定是一樣的
  * andOperator() 這個方法就是關鍵的方法了,把同key的多個條件組在一起
  * 但是 andOperator() 有個很坑的地方就是,在一個query中只能出現一次
  * 如果你有很固定很明確的入參,那還好,直接呼叫一次 andOperator()
  * 如果是多個key需要多個條件,而且條件數量還是動態的,怕不是魔鬼吧...
  */
query.addCriteria(new Criteria().andOperator(gt,lt));

⑤ 當得知一個query中只能存在一個 andOperator() 方法的時候,就應該把思考方向放在如何

把不確定個數的 Criteria 物件放入一個 andOperator() 方法中,這裡是把多個 Criteria 物件用

逗號分隔的,其實 andOperator() 方法還可以入參 Criteria[] 陣列

定義陣列的話,那麼問題又來了,如何確定陣列的長度...即使定義了一個 [1024] 這樣長度的陣列

那如果邏輯中還有 if 判斷隔開了,那陣列的下標如何保證連續不錯誤,於是就又定義了一個List<Criteria>

泛型集合,先往集合裡面存,完事了後就把集合遍歷放入陣列,最後把陣列入參到 andOperator() 方法

//定義一個泛型集合,型別為 Criteria
List<Criteria> criteriaList = new ArrayList<>();
//定義一個無長度的陣列,型別為 Criteria
Criteria[] criteriaArray = {};
//往集合裡面新增條件物件
if(你的邏輯){
    //大於方法
    Criteria gt = Criteria.where("你MongoDB中的key").gt("你的條件");
    //小於方法
    Criteria lt = Criteria.where("你MongoDB中的key").lt("你的條件");
    if(gt!=null && lt!=null){
        criteriaList.add(gt);
        criteriaList.add(lt);
    }else if(gt!=null){
        query.addCriteria(gt);
    }else if(lt!=null){
        query.addCriteria(lt);
    }
}
//是否有條件
if(criteriaList.size()>0){
    //把無長度的陣列例項出來,長度就位集合的個數
    criteriaArray = new Criteria[criteriaList.size()];
    for(int i = 0 ; i < criteriaList.size() ; i++){
        //把集合中的條件物件全部存入陣列中
        criteriaArray[i] = criteriaList.get(i);
    }
}
//最後把陣列入參到 andOperator() 方法中
query.addCriteria(new Criteria().andOperator(criteriaArray));

⑥ 最後一步,呼叫 mongoTemplate 物件的 find() 方法

/**
  * xxxxx 即為實體類,也是此方法返回泛型型別
  * 如 xxxxx 為 Student (Student.class),那麼此方法就會返回 List<Student>
  */
mongoTemplate.find(query,xxxxx.class,collectionName);

 3. 連貫程式碼例項,因為沒有寫demo,程式碼中有很多敏感資訊,我就替換成文字說明,但是我會盡量

寫的通俗易懂

/**
  *    定義了一個方法,返回型別就是等會最後入參的 xxxxx.class 型別的泛型集合
  *    引數
  *              條件  --- > 條件集合
  *    collectionName  --- > MongoDB的集合名稱
  */
public List<返回型別> getXxxxxByCollectionNameAndCondition(List<條件型別> 條件,String collectionName) throws Exception{


    //用來封裝所有條件的物件
    Query query = new Query();
    //用來構建條件
    Criteria criteria = new Criteria();
    
    /**
      * 這裡最多會出現兩個多條件的key
      * 所以我定義了兩個集合和兩個陣列
      */

    //定義一個泛型集合,型別為 Criteria
    List<Criteria> criteriaList_first = new ArrayList<>();
    //定義一個無長度的陣列,型別為 Criteria
    Criteria[] criteriaArray_first = {};

    //定義一個泛型集合,型別為 Criteria
    List<Criteria> criteriaList_second = new ArrayList<>();
    //定義一個無長度的陣列,型別為 Criteria
    Criteria[] criteriaArray_second = {};


    //遍歷所有條件
    for(條件型別 條件物件 : 條件){
        if(條件物件){
            //往集合裡面新增條件物件
            if(你的邏輯){
                //大於方法
                Criteria gt = Criteria.where("你MongoDB中的key").gt("你的條件");
                //小於方法
                Criteria lt = Criteria.where("你MongoDB中的key").lt("你的條件");
                if(gt!=null && lt!=null){
                    criteriaList_first.add(gt);
                    criteriaList_first.add(lt);
                }else if(gt!=null){
                    query.addCriteria(gt);
                }else if(lt!=null){
                    query.addCriteria(lt);
                }
            }else if(你的邏輯){
                //大於方法
                Criteria gt = Criteria.where("你MongoDB中的key").gt("你的條件");
                //小於方法
                Criteria lt = Criteria.where("你MongoDB中的key").lt("你的條件");
                if(gt!=null && lt!=null){
                    criteriaList_second.add(gt);
                    criteriaList_second.add(lt);
                }else if(gt!=null){
                    query.addCriteria(gt);
                }else if(lt!=null){
                    query.addCriteria(lt);
                }
            }else if(你的邏輯){
                ...
            }
        }else if(其他條件物件){
            ...
        }
        
    }
    
    //是否有條件
    if(criteriaList_first.size()>0){
        //把無長度的陣列例項出來,長度就位集合的個數
        criteriaArray_first = new Criteria[criteriaList_first.size()];
        for(int i = 0 ; i < criteriaList_first.size() ; i++){
            //把集合中的條件物件全部存入陣列中
            criteriaArray_first[i] = criteriaList_first.get(i);
        }
    }

    //是否有條件
    if(criteriaList_second.size()>0){
        //把無長度的陣列例項出來,長度就位集合的個數
        criteriaArray_second = new Criteria[criteriaList_second.size()];
        for(int i = 0 ; i < criteriaList_second.size() ; i++){
            //把集合中的條件物件全部存入陣列中
            criteriaArray_second[i] = criteriaList_second.get(i);
        }
    }
    
    //如果兩個引數陣列中任意一個存在值
    if(criteriaArray_first.length > 0 || criteriaArray_second.length > 0){
         //呼叫合併陣列方法,併入參到query中(合併陣列的方法緊接著下面寫了)
         query.addCriteria(new Criteria().andOperator(this.concat(criteriaArray_first,criteriaArray_second)));
    }
    
    //呼叫 find() 方法並返回
    return mongoTemplate.find(query,返回型別.class,collectionName);

}


/**
  *    把兩個數組合併為一個數組
  */
private Criteria[] concat(Criteria[] criteria1 , Criteria[] criteria2){
        Criteria[] c= new Criteria[criteria1.length+criteria2.length];
        System.arraycopy(criteria1, 0, c, 0, criteria1.length);
        System.arraycopy(criteria2, 0, c, criteria1.length, criteria2.length);
        return c;
}

4. 到此全部程式碼已經寫完了

希望能夠幫助到你

over