mongoTemplate实战
目录
一、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:客户端最大连接数,超过了将会被阻塞,默认100threads-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,单位millisecondsread-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")); } } }
标签:
上一篇: linux 服务器性能监控(一)
下一篇: nginx配置个https+backlog+sysctl.conf