一、前言
最近項目使用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;
}