MongoTemplate的实战

ε祈祈猫儿з 提交于 2020-08-16 08:24:07

                     MongoTemplate的实战

目录

一、Mavn依赖:

二、实例化mongoTemplate

1、client-options配置详解

2、MappingMongoConverter

三、语法

1.条件查询:

2.模糊查询

3.分页查询

4.对查询进行排序

5.查询总数:

6.新增

7.更新操作:

8.删除操作:

9、集合的判断与创建

10、--andOperator--方法

11、聚合group


一、Mavn依赖:

        
        <!--spring data jars-->
        <dependency>
        <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
        </dependency>
        <dependency>
        <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
        </dependency>
        <!-- mongodb驱动-->
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
        </dependency>

 

二、实例化mongoTemplate


1、client-options配置详解

min-connections-per-host:客户端最小连接数
connections-per-host:客户端最大连接数,超过了将会被阻塞,默认100
threads-allowed-to-block-for-connection-multiplier:可被阻塞的线程数因子,默认值为5,如果connectionsPerHost
配置为10,那么最多能阻塞50个线程,超过50个之后就会收到一个异常
max-wait-time:阻塞线程获取连接的最长等待时间,默认120000 ms
max-connection-idle-time:连接池连接最大空闲时间
max-connection-life-time:连接池连接的最大存活时间
connect-timeout:连接超时时间,默认值是0,就是不超时
socket-timeout:socket超时时间,默认值是0,就是不超时
socket-keep-alive:keep alive标志,默认false
server-selection-timeout:服务器查询超时时间,它定义驱动在抛出异常之前等待服务器查询成功,默认30s,单位milliseconds
read-preference:MongoDB有5种ReadPreference模式:
	primary    主节点,默认模式,读操作只在主节点,如果主节点不可用,报错或者抛出异常。
    primaryPreferred   首选主节点,大多情况下读操作在主节点,如果主节点不可用,如故障转移,读操作在从节点。
    secondary    从节点,读操作只在从节点, 如果从节点不可用,报错或者抛出异常。
    secondaryPreferred    首选从节点,大多情况下读操作在从节点,特殊情况(如单主节点架构)读操作在主节点。
    nearest    最邻近节点,读操作在最邻近的成员,可能是主节点或者从节点。
write-concern:WriteConcern的7种写入安全机制抛出异常的级别:
    NONE:没有异常抛出
    NORMAL:仅抛出网络错误异常,没有服务器错误异常,写入到网络就返回
    SAFE:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。
    MAJORITY: 抛出网络错误异常、服务器错误异常;并多数主服务器完成写操作。
    FSYNC_SAFE: 抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。
    JOURNAL_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。
    REPLICAS_SAFE:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作。
heartbeat-frequency:驱动用来确保集群中服务器状态的心跳频率
min-heartbeat-frequency:驱动重新检查服务器状态最少等待时间
heartbeat-connect-timeout:集群心跳连接的超时时间
heartbeat-socket-timeout:集群心跳连接的socket超时时间
ssl:驱动是否使用ssl进行连接,默认是false
ssl-socket-factory-ref:用来进行ssl连接的SSLSocketFactory,如果配置为none,则使用SSLSocketFactory.getDefault()

2、MappingMongoConverter


调用mongoTemplate的save方法时, spring-data-mongodb的TypeConverter会自动给document添加一个_class属性, 值是你保存的类名. 这种设计并没有什么坏处. spring-data-mongodb是为了在把document转换成Java对象时能够转换到具体的子类. 但有时候我们并不希望出现这个字段, 主要是看上去会比较"烦". 可以通过设置MappingMongoConverter的MongoTypeMapper来解决这个问题. 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd">

    <mongo:mongo-client id="mongo" host="127.0.0.1" port="27017" credentials="user:pass@test">
        <mongo:client-options write-concern="NORMAL" />
    </mongo:mongo-client>

     <mongo:db-factory id="mongoDbFactory" dbname="test" mongo-ref="mongo"/>
    
<!-- 添加这部分可以入库时屏蔽掉_class字段-->
    <bean id="mappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
    <bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
    <constructor-arg name="typeKey">
    <null />
    </constructor-arg>
    </bean>

    <bean id="mappingMongoConverter" class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    <constructor-arg name="mappingContext" ref="mappingContext" />
    <property name="typeMapper" ref="defaultMongoTypeMapper" />
    </bean>

     <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
    <constructor-arg name="mongoConverter" ref="mappingMongoConverter" />
     </bean>
</beans>


三、语法


1.条件查询:

// 再实例化一个条件对象
Criteria criteria = new Criteria();

// 先实例化一个查询对象,参数为一个Criteria对象
Query query = new Query(criteria );

// 相当于sql:where id = id
criteria = Criteria.where("id").is(id);

// 把query对象和要进行操作的实体类作为参数,find方法为mongoTemplate封装的查询方法
 Aaa aaa = this.mongoTemplate.find(query,Aaa.class);
	

2.模糊查询


// 再实例化一个条件对象
Criteria criteria = new Criteria();

// 先实例化一个查询对象,参数为一个Criteria对象
Query query = new Query(criteria );

// 使用正则表达式实现分词
Pattern pattern = Pattern.compile("^.*" + projectName.toString() + ".*$", Pattern.CASE_INSENSITIVE);

// regex方法相当于sql的like条件
criteria = Criteria.where("project_name").regex(pattern);

// 把query对象和要进行操作的实体类作为参数,find方法为mongoTemplate封装的查询方法
Aaa aaa = this.mongoTemplate.find(query, aaa.class);

3.分页查询

// 再实例化一个条件对象
Criteria criteria = new Criteria();

// 先实例化一个查询对象,参数为一个Criteria对象
Query query = new Query(criteria);

// skip():跳过指定数量的数据;注意需要传入每页的大小和当前页数的参数
criteria.skip(pageSize*(pageNo-1));

//读取的记录条数
criteria.limit(pageSize);

// 把query对象和要进行操作的实体类作为参数,find方法为mongoTemplate封装的查询方法
return this.mongoTemplate.find(query, Aaa.class);

4.对查询进行排序

// 先实例化一个查询对象
Query query = new Query();

// 实例化一个排序对象,参数为排序顺序,和对哪个字段进行排序
Sort sort = new Sort(Sort.Direction.DESC,"id");

// 把sort对象加入query对象中
query.with(sort);

// 把query对象和要进行操作的实体类作为参数,find方法为mongoTemplate封装的查询方法
return this.mongoTemplate.find(query,Aaa.class);

5.查询总数:

// 实例化Criteria,相当于where id = id;
Criteria criteria= Criteria.where("id").is(id);

// 先实例化一个查询对象,参数为一个Criteria对象
Query query=new Query(criteria);

//count():查询记录总数
return this.mongoTemplate.count(query, StarLinkOperateLog.class);

 

6.新增

下面说一下insert和save的区别:
1)插入重复数据时:
  insert: 若新增数据的主键已经存在,则会抛 DuplicateKeyException 异常提示主键重复,不保存当前数据。
  save: 若新增数据的主键已经存在,则会对当前已经存在的数据进行修改操作。


2)批操作时:
  insert: 可以一次性插入一整个列表,不用进行遍历操作,效率相对较高。
  save: 需要遍历列表,进行一个个的插入,效率相对较低。
 


// 插入一条数据
return mongoTemplate.insert(新增的对象);

// 插入多条数据
return mongoTemplate.insertAll(新增的对象列表);

7.更新操作:

更新操作有以下的方法:
1)updateFirst 更改符合条件的第一个记录;
2)updateMulti 如果根据查询条件找到对应的多条记录,则会全部更新;
3)upsert 相当于 update+insert 如果根据条件没有对应的数据,则会进行插入操作;
4)findAndModify 查询然后更新;



// 根据id进行条件查询
Criteria criteria = Criteria.where("id").is(id);

// 实例化一个Query对象,传入条件对象参数
Query query = new Query(criteria);

// 实例化一个update对象
Update update = new Update();

// 指定需要更改的字段,设置新值
update.set("username","the new username");
A
// 传入需要的参数
return this.mongoTemplate.updateFirst(query,update,Aaa.class);

 

8.删除操作:

1)根据条件删除:

// 实例化一个条件对象
Criteria criteria = Criteria.where("id").is(id);

// 实例化一个Query对象,传入条件对象参数
Query query = new Query(criteria);

// 调用remove方法传入条件和进行操作的实体类
return this.mongoTemplate.remove(query,aaa.class);

下面补充两种删除方法说明:
1)findAndRemove:查询出符合条件的第一个结果,并将符合条件的数据删除而且只会删除第一条;

2)findAllAndRemove:查询出符合条件的所有结果,并将符合条件的所有数据删除;


9、集合的判断与创建

1) 判断集合是否存在
mongoTemplate.collectionExists(collectionName)

2) 创建集合
mongoTemplate.createCollection(collectionName)


10、--andOperator--方法


1)机制是:新建一个criteria对象放到当前criteria对象的criteriaChain属性中。
关于这个新建的criteria对象:它的key属性是”$and”,它的isValue值比较特别,是一个list集合,集合中是dbObject对象。

2)“$and”如何工作
向good中插入100W数据。

for (var i=0; i<1000000; i++) {  
    db.good.insert({"x":[i, i+1, i+2, i+3, i+4]});  
}  

执行查询,查看是否有$and的区别

$and和不加$and的区别在于:   
> db.good.find({"x":{"$lt":5,"$gt":1}})//相当于加了"$and" 
{ "_id" : ObjectId("4ed061427ecbeebf00e65625"), "x" : [ 0, 1, 2, 3, 4 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65626"), "x" : [ 1, 2, 3, 4, 5 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65627"), "x" : [ 2, 3, 4, 5, 6 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65628"), "x" : [ 3, 4, 5, 6, 7 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65629"), "x" : [ 4, 5, 6, 7, 8 ] }   

> db.good.find({"x":{"$lt":5}, "x":{"$gt":1}})  
{ "_id" : ObjectId("4ed061427ecbeebf00e65625"), "x" : [ 0, 1, 2, 3, 4 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65626"), "x" : [ 1, 2, 3, 4, 5 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65627"), "x" : [ 2, 3, 4, 5, 6 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65628"), "x" : [ 3, 4, 5, 6, 7 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e65629"), "x" : [ 4, 5, 6, 7, 8 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e6562a"), "x" : [ 5, 6, 7, 8, 9 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e6562b"), "x" : [ 6, 7, 8, 9, 10 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e6562c"), "x" : [ 7, 8, 9, 10, 11 ] }   
{ "_id" : ObjectId("4ed061427ecbeebf00e6562d"), "x" : [ 8, 9, 10, 11, 12 ] }  
......  

11、聚合group

1) 而mongoDB没提供SQL那样通过Group By就轻松实现数据库的分组功能,我们通过接口来实现的

   db.collection.group({ key, reduce, initial[, keyf] [, cond] [, finalize] })

key

作为分组的key

reduce

一个聚合函数操作文档的分组操作期间。这些函数可以返回一个sum或count。该函数接受两个参数:当前文档和这个群体聚集的结果文档。

initial

初始化聚合结果文档变量,为空时自动为每列提供初始变量。

keyf

可选。替代的key 字段。指定一个函数创建一个“key object”作为分组的key。使用keyf而是通过group by领域而不是现有的文档域键组。

cond

过滤条件

finalize

在db.collection.group()返回最终结果之前,此功能可以修改的结果文档或替换的结果文档作为一个整体。

 预备数据:MonogoDB数据库中添加了订单的数据

/* 0 */
{
 "_id" : ObjectId("552a330e05c27486b9b9b650"),
 "_class" : "com.mongo.model.Orders",
 "onumber" : "002",
 "date" : ISODate("2014-01-03T16:03:00Z"),
 "cname" : "zcy",
 "item" : {
   "quantity" : 1,
   "price" : 4.0,
   "pnumber" : "p002"
  }
}
 
/* 1 */
{
 "_id" : ObjectId("552a331d05c275d8590a550d"),
 "_class" : "com.mongo.model.Orders",
 "onumber" : "003",
 "date" : ISODate("2014-01-04T16:03:00Z"),
 "cname" : "zcy",
 "item" : {
   "quantity" : 10,
   "price" : 2.0,
   "pnumber" : "p001"
  }
}
 
/* 2 */
{
 "_id" : ObjectId("552a333105c2f28194045a72"),
 "_class" : "com.mongo.model.Orders",
 "onumber" : "003",
 "date" : ISODate("2014-01-04T16:03:00Z"),
 "cname" : "zcy",
 "item" : {
   "quantity" : 30,
   "price" : 4.0,
   "pnumber" : "p002"
  }
}
 
/* 3 */
{
 "_id" : ObjectId("552a333f05c2b62c01cff50e"),
 "_class" : "com.mongo.model.Orders",
 "onumber" : "004",
 "date" : ISODate("2014-01-05T16:03:00Z"),
 "cname" : "zcy",
 "item" : {
   "quantity" : 5,
   "price" : 4.0,
   "pnumber" : "p002"
  }
}

我们要对日期和产品编码进行分组,并计算相同的产品的数量

 MongoDB:

       db.orders.group({

          key: { date:1,'item.pnumber':1},

          initial : {"total":0},

         reduce : function Reduce(doc, out) {

        out.total+=doc.item.quantity

   } });

2)Spring Data MongoDB 提供了Group有几个接口

  GroupCommand  groupCommand=new GroupCommand(inputCollection, keys, condition, initial, reduce, finalize);

我们要对日期和产品编码进行分组,并计算相同的产品的数量

public void getGroupCount(String collectionName) {
		
		BasicDBObject key = new BasicDBObject(); 
		key.put("date", 1);
		key.put("item.pnumber", 1);
		//条件
		BasicDBObject cond = new BasicDBObject();  
		//初始化
		BasicDBObject initial = new BasicDBObject();  
		initial.append("total", 0);  
		//reduce
		String reduce = "function Reduce(doc, out) { " +  
		        "  out.total+=doc.item.quantity;" +  
		        "}";  
		
		SimpleDateFormat format=new SimpleDateFormat("yyyy-mm-dd");
		BasicDBList groupList=(BasicDBList) mongoTemplate.getCollection(collectionName).group(key, cond, initial, reduce);
		if(groupList!=null&&groupList.size()>0){
			System.out.println("date  item.pnumber  total");
			for(int i=0;i<groupList.size();i++){ 
				BasicDBObject obj=(BasicDBObject) groupList.get(i);
				System.out.println(format.format(obj.getDate("date"))+"  "+obj.getString("item.pnumber")+"  "+obj.getInt("total"));
			}
		}
	}


 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!