SpringData實現Mongodb的CRUD:MongoTemplate框架


    MongoTemplate實現了java代碼與mongodb數據庫之間的連接,是現場安全的。

一.創建MongoTemplate實例。

    1.java code創建

      1.1)數據庫無密碼:

          MongoClient mongoClient = new MongoClient( "localhost" , 27017 );

          //"dbName":連接的數據庫集合名稱

          SimpleMongoDbFactory dbFactory = new SimpleMongoDbFactory(mongoClient , "dbName"); 

          DbRefResolver dbRefResolver = new DefaultDbRefResolver(dbFactory);

          MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext());

         converter.setTypeMapper(new DefaultMongoTypeMapper(null));

         //加入converter是去掉數據庫文檔中_class字段

         MongoTemplate template = new MongoTemplate(dbFactory, converter);

      1.2)數據庫有密碼驗證

      UserCredentials userCredentials = new UserCredentials( "username", "password" );

      SimpleMongoDbFactory dbFactory = new SimpleMongoDbFactory(mongoClient , "dbName",userCredentials );

                 .....................(下步驟同上).....................

二.MongoTemplate的Crud操作mongodb數據庫

     /* 約定 */

     /*object:新增的javaBean對象。collectionName:集合名稱,相當於表名。*/

    /*Collection<? extends Object> collection:批量操作時,對象的集合。例如List<User> collection*/

    /*Query query = new Query()    query:條件*/

    1.新增文檔

     MongoTemplate提供了save()和insert()兩種方式。

     save:新增文檔時,如果有_id文檔存在則修改,不存在則增加,相當於根據條件調用insert或update方法。

     insert:新增文檔時,如果有_id文檔存在則會新增失敗,即不會修改之前的值,也不會重新增加。

     用法:

                template.save(object);

                template.save(object,collectionName);

               template.insert(object);

               template.insert(object,collectionName);

               //批量插入

               template.insertAll(collection);

               template.insert(collection,collectionName);

   2.刪除文檔

                template.remove(query,collectionName);

                template.dropCollection(collectionName);//刪除集合,即該張表會被刪除

  3.修改文檔

               . updateFirst   只修改符合條件第一條數據

               . updateMulti  修改符合條件的所有所有

               . upsert          修改符合條件時如果不存在則會新增加一條數據,相當於執行了insert()方法

               /************ Update update=new Update() : update 需要更新的內容 *****************************/

update.set("key1", "value1")  把"key1"對應的值設置為"value1",如果數據中不存在"key1",則會新增加一條信息key1:value1
update.inc("sum", 100) inc累加計算,即sum在原來基礎上加上100,相當於sum=sum+100
update.multiply("sum", 100) 乘法計算,即sum在原來基礎上乘以100,相當於sum=sum*100
update.rename("key2", "k2") rename用於修改鍵值, 即把"key2":"value2"修改為"k2":"value2"
update.unset("key3") 刪除鍵為"key3"的信息,即從文檔中移除該鍵
update.pull("array", "a1") 刪除array數組中的"a1"。 例如"array":["a1","a2","a3"],刪除"a1"后的結果 "array":["a2","a3"]
update.pullAll("array", Object[] values) 可一次性刪除數組內多個值
update.push("array","a3") 向array數組里添加"a3"(不會檢查數組中元素是否重復), 數組"array"不存在則會新建該數組。修改后結果"array":["a2","a3","a3"]
update.pushAll("array", Object[] values) 可一次性向數組內添加多個值
update.addToSet("array","a3") 向array數組里添加"a3"(會檢查數組中元素是否重復), 數組"array"不存在則會新建該數組。修改后結果"array":["a2","a3"]
update.pop("array",Update.Position.FIRST) 從"array"數組 開頭/結尾(Update.Position.FIRST/Update.Position.LAST) 移除一個元素

          /*****************************  執行更新操作 *************************************/

                   //更新符合query條件的第一條數據

                   template.updateFirst(query, update, collectionName);

                   //更新符合query條件的所有數據

                   template.updateMulti(query, update, collectionName);

                  //更新符合條件時如果不存在則會新增加一條數據,相當於執行了insert()方法

                   template. upsert(query, update, collectionName);

    4.查詢操作

/**************************** 准備query *****************************************/     

                          Query query=new Query();

                          Query query=new Query(CriteriaDefinition criteriaDefinition);

     !CriteriaDefinition是接口,Criteria是其實現類

/**************************** 設置query條件 *****************************************/ 

一些常用的Query方法
返回類型 方法 說明 應用例子
Query addCriteria(Criteria criteria) 向query里追加查詢條件 query.addCriteria(Criteria.where("name").is("jack"));
Query  skip(int skip) 從第skip下標數據開始查詢,跳過skip下標之前的數據,小標從0開始 query.skip(skip);
Query  limit(int limit) 限制返回數據的最大條數 query.limit(limit);
Query  withHint(String name) 做強迫索引查詢用  
Query  with(Sort sort) 可用於排序用

query.with(new Sort(Sort.Direction.DESC,"time"));

query.with(new Sort(Sort.Direction.ASC,"time"));

Query with(Pageable pageable) Pageable對象里有skip,limit,sort信息,所以做可以分頁和排序  
static Query query(Criteria criteria)   Query.query(Criteria.where("name").is("jack"));
DBObject  getQueryObject()     
Field fields()

Field 可用於做指定字段查詢query.fields().include("age").exclude("name");

還可用做返回指定字段時的工具(后面有例子)

query.fields()

 

Criteria類常用方法
static Criteria where(String key) 創建一個key,即查詢的key鍵 query.addCriteria(Criteria.where("name").is("jack"));
static Criteria

byExample(Object example)

  () 
static Criteria

byExample(Example<?> example)

   ()
Criteria is(Object obj) 等於(==) obj  query.addCriteria(Criteria.where("name").is("obj"));
Criteria and(String key) 並且,用於多個字段同時查詢  query(where("key1").is("value1").and("key2").is("value2")); 
Criteria ne(Object o) 不為 (不等於)

query(where("siteId").ne(null));//查詢siteId不為空的數據

query(where("name").ne("不為該值"));//

Criteria lt(Object o) 小於(<

query.addCriteria(Criteria.where("insert_date").gte(Date1).lte(Date2));

query.addCriteria(Criteria.where("age").gte(20).lte(30));

Criteria lte(Object o) 小於等於(<=
Criteria gt(Object o) 大於(>)
Criteria gte(Object o) 大於等於(>=)
Criteria

in(Object... co)

 在...里(key對應的數據被包含在 co 里)

    String[] strs=... ;

query.addCriteria(Criteria.where("name").in((Object[]) strs));

或query.addCriteria(Criteria.where("name").in(obj1,obj2,obj3,...));

Criteria

in(Collection<?> co)

   List<Object> collec=...;

query.addCriteria(Criteria.where("key").in(collec));

Criteria

nin(Object... o)

不在...里(與in相反)      (略)
Criteria

nin(Collection<?> o)

Criteria mod(Number value, Number remainder)

取模(求余)運算 ,即:key對應的值%value==remainder(求余是否等於remainder)

   // {key:15} {key2:15}

query.addCriteria(Criteria.where("key").mod(10,3)); 

 //key條件不成立;key2條件成立

Criteria

all(Object... col)

key鍵對應的集合包含col(all是包含關系,in是被包含關系)

query.addCriteria(Criteria.where("key").all("n1","n2"));//此時key對應的值應該是集合 

query.addCriteria(Criteria.where("nameList").all((Object[]) names)));

Criteria

all(Collection<?> col)

     List<Object> collec=...;

query.addCriteria(Criteria.where("key").all(collec));

Criteria

size(int s)

匹配key所對應的集合的元素的指定數量(!!!不能進行像<5之類的范圍匹配) 

 // {key:["foo","lue","cua"]}

query.addCriteria(Criteria.where("key").size(3));

Criteria exists(boolean b) 查詢字段是否存在(true:存在,false:不存在)  query.addCriteria(Criteria.where("confirmTime").exists(false));
Criteria type(int t)    
Criteria not() 取反  

      //注意:not().is()這樣是錯誤的,not()后面不用跟is()

  query.addCriteria(Criteria.where("number").not().lte(2)); //number<=2取反,即number>2

Criteria regex(String re) 模糊查詢用  (例子見下)
Criteria regex(String re, String options)

options可選值:i/m/x/s

//i表示不區分大小寫

//m能使用^以及$等正則表達式來識別數據庫中使用\n換行的每一行開始字符以及字符。

//x

//s如果設置了這個修飾符,模式中的點號元字符匹配所有字符,包含換行符。如果沒有這個修飾符,點號不匹配換行符。

Criteria regex(Pattern pattern)

Pattern pattern = Pattern.compile("正則表達式"); 

query.addCriteria(Criteria.where("resourceName").regex(pattern));

       
Criteria  orOperator(Criteria... criteria)

多個Criteria多個條件的或(or)操作

(a || b)

Criteria c1=Criteria.where("name").is("張三"));

Criteria c2=Criteria.where("age").is(25));

query.addCriteria(new Criteria().orOperator(c1, c2)); 

Criteria  norOperator(Criteria... criteria)

執行mongodb的$nor操作,意思是:

返回 不滿足$or條件 的文檔

即返回 不滿足(a || b)的文檔

 (語法同orOperator)
Criteria  andOperator(Criteria... criteria)

多條件(and)操作

(a && b

(同orOperator
Criteria  elemMatch(Criteria c)

對象數組里的參數查詢

"users":[{"name":"張三","age":20,"hobby":"internet"},{},...]

Criteria cri=Criteria.where("name").is("張三"));

query.addCriteria(Criteria.where(users).elemMatch(cri);

Criteria  registerCriteriaChainElement(Criteria criteria)    
       
Criteria alike(Example<?> sample)    
Criteria withinSphere(Circle circle)    
Criteria within(Shape shape)    
Criteria near(Point point)    
Criteria nearSphere(Point point)    
Criteria intersects(GeoJson geoJson)    
Criteria maxDistance(double maxDistance)    
Criteria minDistance(double minDistance)    
       
boolean lastOperatorWasNot()    
Pattern toPattern(String regex, String options)    
String getKey()    
DBObject getCriteriaObject()    
DBObject getSingleCriteriaObject()    
BasicDBList createCriteriaList(Criteria[] criteria)    
void setValue(DBObject dbo, String key, Object value)    
boolean createNearCriteriaForCommand(String command, String operation, double maxDistance)    
boolean simpleCriteriaEquals(Criteria left, Criteria right)    
boolean isEqual(Object left, Object right)    
int hashCode()    
static boolean requiresGeoJsonFormat(Object value)    

    /** 利用regex做迷糊查詢 **/  

       private String regexFilter(String regex) {
             if (regex.equals("*")) {
                   return "\\" + regex;
             } else {
                 return regex;
             }
         }

      query.addCriteria(Criteria.where("name").regex(".*" + regexFilter("StringValue") + ".*"));

   /****/

 

  /**************************** 分頁 *****************************************/

        方式一:   

             (單個字段排序)

            query.with(new Sort(Sort.Direction.DESC,"time"));

            query.with(new Sort(Sort.Direction.ASC,"time"));

              (多個字段同事排序)

             query.with(new Sort(Direction.ASC,"time1","time2","time3"));

              (不同字段不同排序)

             List<Sort.Order>orderList=new ArrayList<Sort.Order>();  

             orderList.add(new Sort.Order(Direction.ASC, "time1"));  

             orderList.add(new Sort.Order(Direction.DESC, "tim2"));  

             query.with(new Sort(orderList));  

              先按照time1升序,在按照time2降序

       方式二:

             int page=3;//第幾頁
             int size=30;//每頁條數
             Sort sort=new Sort(Sort.Direction.ASC, "update_time");//排序,多條件排序同上
             Pageable pageable=new PageRequest(page, size, sort);
             query.with(pageable);

/**************************** 排序 *****************************************/ 

     方式一:

       query.skip(skip);

       query.limit(limit);

     方式二:

        (同上—分頁)

/**************************** 返回指定字段 *****************************************/ 

     利用 BasicQuery指定返回的字段

    方式一:

     BasicDBObject queryObject=new BasicDBObject();

     BasicDBObject  fieldsObject=new BasicDBObject();//fieldsObject可以指定返回字段

     fieldsObject.put(key,val);

      //key:數據庫的字段

      //val:1或true表示返回;0或false表示不返回。

      !注:_id默認是1,沒指定返回該字段時,默認會返回,只有設置為0就不會返回該字段。

      Query query=new BasicQuery(queryObject, fieldsObject)

     方式二:(利用 Field 類)

     BasicDBObject queryObject=new BasicDBObject();

     Field  field = new Field();  

     field.exclude("key1");//不返回key1,等同於把 fieldsObject.put(key,val)的val設置為0.

     field.include("key2");//返回key2,等同於把 fieldsObject.put(key,val)的val設置為1.

     BasicDBObject  fieldsObject=field.getFieldsObject();

     Query query=new BasicQuery(queryObject, fieldsObject);

 

 /**************************** 執行template *****************************************/ 

     collectionName:數據庫集合名,即表名。

     query:上面生成的條件。

     entityClass:返回的數據被映射成的類型。

 

MongoTemplate提供的一些常用crud方法
返回類型 方法名 example 說明
<T> T findOne(Query query, Class<T> entityClass, String collectionName) User user=template.findOne(query, User.class, "collectionName"); 查詢返回一條數據
<T> List<T>  find(Query query, Class<T> entityClass, String collectionName) List<User> users= template.find(query, User.class, "collectionName"); 查詢滿足條件的所有 
<T> List<T> findAll(Class<T> entityClass, String collectionName)  List<User> users= template.findAll(User.class, "collectionName");  查詢該張表所有數據 
<T> List<T> 

findAllAndRemove(Query query,Class<T> entityClass,String

collectionName) 

   
<T> T  findAndRemove(Query query, Class<T> entityClass, String collectionName)     
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName)     
<T> T  findById(Object id, Class<T> entityClass, String collectionName)     
       
             插入(新增)相關方法  
void  save(Object objectToSave, String collectionName) 

User user=.....;

template.save(user, "collectionName"); 

 
void  insert(Object objectToSave, String collectionName)   template.insert(user, "collectionName");   存入單個對象 
void  insert(Collection<? extends Object> batchToSave, String collectionName) 

List<User> users=....;

template.insert(users, "collectionName"); 

可以存入對象集合 
       
          刪除相關方法
void  dropCollection(String collectionName)    該張表全部數據會被刪除 
WriteResult remove(Query query, String collectionName)  template.remove(query, "collectionName");   
WriteResult  remove(Query query, Class<?> entityClass, String collectionName)     
       
        修改文檔相關方法
WriteResult  updateFirst(Query query, Update update, String collectionName) template.updateFirst(query, update, "collectionName"); //更新符合query條件的第一條數據
WriteResult  updateFirst(Query query, Update update, Class<?> entityClass, String collectionName)    
WriteResult  updateMulti(Query query, Update update, String collectionName) template.updateMulti(query, update, "collectionName"); //更新符合query條件的所有數據
WriteResult  updateMulti(Query query, Update update, Class<?> entityClass, String collectionName)    
WriteResult  upsert(Query query, Update update, String collectionName) templateupsert(query, update, collectionName);  //更新符合條件時如果不存在則會新增加一條數據,相當於執行了insert()方法
WriteResult  upsert(Query query, Update update, Class<?> entityClass, String collectionName)    
       
       統計數據數量
long  count(Query query, String collectionName)     
       
     查詢是否存在
boolean exists(Query query, String collectionName)    
       
       
       

         

 /**  分組,聚合查詢group **/

方法一:利用 類 DBCollection 的 group 方法。

       方法:1.DBObject group(DBObject key, DBObject cond, DBObject initial, String reduce);

               2.DBObject group(DBObject key, DBObject cond, DBObject initial, String reduce, String finalize);

               3.DBObject group(DBObject key, DBObject cond, DBObject initial, String reduce, String finalize, ReadPreference readPreference)

  1. key:指定一個或多個文檔字段進行分組。和keyf兩者必須有一個
  2. keyf:可以接受一個javascript函數。用來動態的確定分組文檔的字段。和key兩者必須有一個
  3. initial:reduce中使用變量的初始化, 初始化聚合結果文檔。
  4. reduce:執行的reduce函數。函數需要返回值。
  5. cond:執行過濾的條件。
  6. finallize:在reduce執行完成,結果集返回之前對結果集最終執行的函數。可選的

    DBCollection dbc=template.getCollection("collectionName");

    String reduce = "function(doc,prev){\n" +
                          " prev.count+=1; \n" +
                          " }";

    DBObject  key=new BasicDBObject("state",1);

    DBObject cond=query.getQueryObject();

    DBObject initial=new BasicDBObject("count",0);

    DBObject result = dbc.group(key, cond, initial, reduce);

    Map map = result.toMap();

    for (Map.Entry o : map.entrySet()) {

        System.out.println(o.getKey() + " " + o.getValue());

    }

    

方法二:aggregate聚合

      方法:aggregate(Aggregation aggregation, String collectionName, Class<O> outputType);

  1. Aggregation aggregation
  2. TypedAggregation<?> aggregation
  3. Class<O> outputType: 輸出類型,可以指定具體的實體類型。
  4. String inputCollectionName:。
  5. Class<?> inputType:一個輸入類型,也就是對哪個集合進行操作。
  6. String collectionName:

      

     !注:Aggregation 提供了一系列mongoDB的操作方法,比如match,unwind,limit...等等。

      Criteria criteria = where("...").....

     AggregationOperation match = new MatchOperation(criteria);

      

     UnwindOperation unwind = new UnwindOperation(Fields.field("values"));

     SortOperation sort = new SortOperation(new Sort("..."));

  

    AggregationOperation group = new GroupOperation(Fields.fields("deviceId")).first("deviceId").as("deviceId").count().as("value");

    

   AggregationOperation projection = new ProjectionOperation(fields("events")).and("_id").as("deviceId").andExclude("_id");

         

     Aggregation aggregation = Aggregation.newAggregation(match, unwind, sort, group, projection);

     AggregationResults<User> aggRes = mongoTemplate.aggregate(aggregation, "collectionName", User.class);

     List<User> listUser = aggRes.getMappedResults();

    (一般可用 BasicDBObject 這個類接受,而不用User)

 


免責聲明!

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



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