MongoTemplate 分組分頁復合條件查詢


一、前言

最近項目使用MongoDB作為數據主要存取的地方

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

維護數據無非就是增刪改查,而里面最復雜的就是查詢了

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

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

個人建議點擊這里,花三十分鍾初步了解一下MongoDB

ok,正文開始

二、正文

1.使用mongoTemplate對象常常會調用如下兩種方法

          ① findAll(Class<T> entityClass, String collectionName) 

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

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

                     轉換為指定的類類型。

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

② find(Query query, Class<T> entityClass, String collectionName)

分析:此方法三個參數,與①不同的是,多了第一個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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM