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