Spring-data-mongodb使用手册

合集下载

Springdatamongodb聚合,投射,内嵌数组文档分页.

Springdatamongodb聚合,投射,内嵌数组文档分页.

Springdatamongodb聚合,投射,内嵌数组⽂档分页.尽量别直接⽤ DBObject ,Spring data mongodb 的api 本来就没什么多⼤⽤处,如果还直接⽤ DBObject 那么还需要⾃⼰去解析结果,说动做个对象映射,累不累Spring data mongodb 唯⼀好处就是,不需要⾃⼰decode encode,其他别的⼏乎也没了DBObject project = new BasicDBObject("$project", new BasicDBObject("_id", 1).append("..", "$..").append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1).append("..", 1));query.add(project);query.add(new BasicDBObject("$unwind", "$..."));query.add(new BasicDBObject("$skip",...));query.add(new BasicDBObject("$limit",...));AggregationOutput aggregationOutput = mongoTemplate.getCollection("...").aggregate(query);以下使⽤Spring data mongodb 做聚合,内嵌⽂档分页,订单 - 明细⼀对多的例⼦package com.example.mongo.entity;import lombok.Data;import lombok.experimental.Accessors;import org.bson.types.ObjectId;import org.springframework.data.annotation.Id;import java.io.Serializable;import java.util.List;/*** Created by laizhenwei on 2017/11/9*/@Data@Accessors(chain = true)public class Order implements Serializable {private static final long serialVersionUID = 4738576111790390042L;@Idprivate ObjectId objectId;private List<Detail> details;/*** 企业编号*/private String compyCode;/*** 订单号*/private String orderNo;/*** ⽤户名*/private String userName;}明细实体package com.example.mongo.entity;import lombok.Data;import lombok.experimental.Accessors;import org.bson.types.ObjectId;import java.io.Serializable;import java.math.BigDecimal;/*** Created by laizhenwei on 2017/11/9*/@Data@Accessors(chain = true)public class Detail implements Serializable {private static final long serialVersionUID = 942116549431791887L;private ObjectId id;/*** 商品名称*/private String productName;/*** 商品数量*/private Long itemQty;/*** 单价*/private BigDecimal price;}Junitpackage com.example.mongo.Repository;import com.example.mongo.entity.Detail;import com.example.mongo.entity.Order;import com.mongodb.BasicDBList;import com.mongodb.DBObject;import lombok.Data;import org.bson.types.ObjectId;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.MongoTemplate;import org.springframework.data.mongodb.core.aggregation.Aggregation;import org.springframework.data.mongodb.core.aggregation.AggregationOperation;import org.springframework.test.context.junit4.SpringRunner;import java.math.BigDecimal;import java.util.ArrayList;import java.util.List;import java.util.Optional;import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;import static org.springframework.data.mongodb.core.aggregation.Aggregation.limit;import static org.springframework.data.mongodb.core.query.Criteria.where;/*** Created by laizhenwei on 2017/11/9*/@RunWith(SpringRunner.class)@SpringBootTestpublic class OrderTests {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate MongoTemplate mongoTemplate;private String[] compyCode = {"123123", "456456", "789789"};private String[] userNames = {"Athos", "Peter", "Nero", "Gavin", "Carter"};/*** 造⼀点数据*/@Testpublic void save() {List<Order> orders = new ArrayList<>(200);for (int i = 0; i < 200; i++) {List<Detail> details = new ArrayList<>(3);for (int j = 0; j < 3; j++) {Detail detail = new Detail();detail.setId(new ObjectId());detail.setItemQty((long) (i + 1));detail.setProductName("产品" + i + "_" + j);detail.setPrice(new BigDecimal(10 + i));details.add(detail);}Order order = new Order();order.setCompyCode(compyCode[i % 3]);order.setUserName(userNames[i % 5]);order.setOrderNo(String.valueOf(i));order.setDetails(details);orders.add(order);}orderRepository.insert(orders);}/*** 内嵌⽂档分页查询*/@Testpublic void pageQuery() {Detail detailDto = new Detail();detailDto.setProductName("产品19_0");List<AggregationOperation> commonOperations = new ArrayList<>(9);commonOperations.add(project("objectId", "details", "compyCode", "orderNo", "userName").and("details").as("detail"));Optional.ofNullable(detailDto.getProductName()).ifPresent(s -> commonOperations.add(match(where("details.productName").is(detailDto.getProductName()))));commonOperations.add(unwind("detail"));List<AggregationOperation> pageOperations = new ArrayList<>(commonOperations);pageOperations.add(skip(1l));pageOperations.add(limit(10));List<AggregationOperation> totalAggOperation = new ArrayList<>(commonOperations);totalAggOperation.add(group().count().as("total"));List<DetailVo> results = mongoTemplate.aggregate(Aggregation.newAggregation(Order.class,pageOperations), Order.class, DetailVo.class).getMappedResults();System.out.println(results.size());DBObject rawResults = mongoTemplate.aggregate(Aggregation.newAggregation(Order.class,totalAggOperation), String.class).getRawResults();BasicDBList result = (BasicDBList)rawResults.get("result");long total = result.isEmpty() ? 0 : Long.parseLong(((DBObject)result.get(0)).get("total").toString());System.out.println("total:" + total);}/*** 结果实体*/@Dataprivate static class DetailVo{@Idprivate ObjectId orderId;private Detail detail;private String compyCode;private String orderNo;private String userName;}}logback 打开⽅便观察<Logger name="org.mongodb.driver" level="debug" /><logger name="org.springframework.data.mongodb.core.MongoTemplate" level="debug" />控制台输出,只取重点,因为skip 了⼀个,所以结果只有2个,总数量是3个13:45:31.740 logback [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Executing aggregation: { "aggregate" : "order" , "pipeline" : [ { "$project" : { "objectId" : "$_id" , "details" : 1 , "compyCode" : 1 , "orderNo" : 1 , "userName" : 1 , "detai 13:45:31.743 logback [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[e9]13:45:31.752 logback [main] INFO org.mongodb.driver.connection - Opened connection [connectionId{localValue:2}] to 192.168.1.9:2702313:45:31.756 logback [main] DEBUG mand - Sending command {aggregate : BsonString{value='order'}} to database e9 on connection [connectionId{localValue:2}] to server 192.168.1.9:2702313:45:31.759 logback [main] DEBUG mand - Command execution completed13:45:31.765 logback [main] DEBUG o.s.d.m.c.i.MongoPersistentEntityIndexCreator - Analyzing class class com.example.mongo.Repository.OrderTests$DetailVo for index information.213:45:31.780 logback [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Executing aggregation: { "aggregate" : "order" , "pipeline" : [ { "$project" : { "objectId" : "$_id" , "details" : 1 , "compyCode" : 1 , "orderNo" : 1 , "userName" : 1 , "detai 13:45:31.780 logback [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[e9]13:45:31.780 logback [main] DEBUG mand - Sending command {aggregate : BsonString{value='order'}} to database e9 on connection [connectionId{localValue:2}] to server 192.168.1.9:2702313:45:31.782 logback [main] DEBUG mand - Command execution completedtotal:3。

SpringBoot中MongoDB注解概念及使用

SpringBoot中MongoDB注解概念及使用

SpringBoot中MongoDB注解概念及使⽤spring-data-mongodb主要有以下注解@Id主键,不可重复,⾃带索引,可以在定义的列名上标注,需要⾃⼰⽣成并维护不重复的约束。

如果⾃⼰不设置@Id主键,mongo会⾃动⽣成⼀个唯⼀主键,并且插⼊时效率远⾼于⾃⼰设置主键。

原因可参考上⼀篇mongo和mysql的性能对⽐。

在实际业务中不建议⾃⼰设置主键,应交给mongo⾃⼰⽣成,⾃⼰可以设置⼀个业务id,如int型字段,⽤⾃⼰设置的业务id来维护相关联的表。

@Document标注在实体类上,类似于hibernate的entity注解,标明由mongo来维护该表。

@Indexed声明该字段需要加索引,加索引后以该字段为条件检索将⼤⼤提⾼速度。

唯⼀索引的话是@Indexed(unique = true)。

也可以对数组进⾏索引,如果被索引的列是数组时,MongoDB会索引这个数组中的每⼀个元素。

也可以对整个Document进⾏索引,排序是预定义的按插⼊BSON数据的先后升序排列。

也可以对关联的对象的字段进⾏索引,譬如User对关联的address.city进⾏索引。

@CompoundIndex复合索引,加复合索引后通过复合索引字段查询将⼤⼤提⾼速度。

写法如上,lastName和age将作为复合索引,数字参数指定索引的⽅向,1为正序,-1为倒序。

⽅向对单键索引和随机存不要紧,但如果你要执⾏分组和排序操作的时候,它就⾮常重要了。

@Field代表⼀个字段,可以不加,不加的话默认以参数名为列名。

@Transient被该注解标注的,将不会被录⼊到数据库中。

只作为普通的javaBean属性。

@DBRef关联另⼀个document对象。

类似于mysql的表关联,但并不⼀样,mongo不会做级联的操作。

先来看⼀下不加DBRef时,mongo保存数据的情况:Article类有String title,List pictureList,两个属性,Picture有⼀个url,⼀个desc属性。

[SpringDataMongoDB]学习笔记--MongoTemplate插入修改操作

[SpringDataMongoDB]学习笔记--MongoTemplate插入修改操作

[SpringDataMongoDB]学习笔记--MongoTemplate插⼊修改操作插⼊操作:直接给个例⼦import static org.springframework.data.mongodb.core.query.Criteria.where;import static org.springframework.data.mongodb.core.query.Criteria.query;…Person p = new Person("Bob", 33);mongoTemplate.insert(p);//还可以多加⼀个参数,来提供collectionname。

⽐如insert(p,"person").Person qp = mongoTemplate.findOne(query(where("age").is(33)), Person.class);collection document的名字有下⾯⼏种⽅式:1. 默认为类名,并且⾸字母⼩写。

⽐如com.test.Person -> person2. 通过在类名上增加标记@Document 来指定。

3. 在执⾏操作时,把collectionname作为参数传递进去。

主要操作: insert,insertAll, save(当object不存在时,执⾏insert)。

更新操作:import static org.springframework.data.mongodb.core.query.Criteria.where;import static org.springframework.data.mongodb.core.query.Query;import static org.springframework.data.mongodb.core.query.Update;...WriteResult wr = mongoTemplate.updateMulti(new Query(where("accounts.accountType").is(Account.Type.SAVINGS)),new Update().inc("accounts.$.balance", 50.00),Account.class);主要操作: updateFirst(更新第⼀个匹配的), updateMulti(更新所有匹配的)upsert操作:template.upsert(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")), update("address", addr), Person.class);先查询,如果没有符合条件的,会执⾏插⼊,插⼊的值是查询值+更新值。

Spring Data MongoDB查询指南

Spring Data MongoDB查询指南

Spring Data MongoDB 查询指南Spring Data MongoDB 中的查询指南1. 概述本文将关注在Spring Data MongoDB 中构建不同类型的查询。

我们将查看使用Query 和Criteria 类查询ducument、自动生成的查询方法、JSON 查询和QueryDSL。

1.1. Maven 依赖如果你希望使用Spring Data MongoDB,你需要加入以下条目到你的pom.xml 文件:<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-mongodb</artifactId><version>1.9.6.RELEASE</version></dependency>最新版本可以在这里找到。

2. Document 查询使用Spring Data 查询MongoDB的一种常见方法是使用Query 和Criteria 类,它们非常接近原生操作。

2.1. is这只是一个使用相等的criterion,让我们看看它是如何工作的。

在以下示例中,我们查找名为Eric 的用户。

让我来看看我们的数据库:[{"_id" : ObjectId("55c0e5e5511f0a164a581907"),"_class" : "er","name" : "Eric","age" : 45},{"_id" : ObjectId("55c0e5e5511f0a164a581908"),"_class" : "er","name" : "Antony","age" : 55}]现在让我们看一下查询代码:Query query = new Query();query.addCriteria(Criteria.where("name").is("Eric"));List<User> users = mongoTemplate.find(query, User.class);该逻辑的返回值将如预期:{"_id" : ObjectId("55c0e5e5511f0a164a581907"),"_class" : "er","name" : "Eric","age" : 45}2.2. 正则表达式正则表达式是一种更灵活、更强大的查询类型。

MongoDB–SpringDataMongoDB详细操作(增删改查)

MongoDB–SpringDataMongoDB详细操作(增删改查)

MongoDB–SpringDataMongoDB详细操作(增删改查)在NoSQL盛⾏的时代,App很⼤可能会涉及到MongoDB数据库的使⽤,⽽也必须学会在Spring boot使⽤Spring Data连接MongoDB进⾏数据增删改查操作,如下为详细的操作⼿册。

依赖直接导⼊spring-data-mongodb包或者使⽤Spring Boot starter<dependencies><!-- other dependency elements omitted --><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-mongodb</artifactId><version>2.2.0.RELEASE</version></dependency></dependencies><!--spring 框架使⽤最新的 --><spring.framework.version>5.2.0.RELEASE</spring.framework.version><!--⽤⼀即可--><!--使⽤Spring Boot starter--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>属性⽂件application.properties#mongodb连接地址,集群⽤“;”隔开spring.mongo.mongoDatabaseAddress=10.110.112.165:27092;10.110.112.166:27092#mongo数据名spring.mongo.dbname=mongodb#mongo⽤户ername=mongodbopr#mongo密码spring.mongo.password=123456#mongo最⼤连接数spring.mongo.connectionsPerHost=50mongoDB 配置注册Mongo实例配置:@Configurationpublic class MongodbConfig {public static final String COMMA = ";";public static final String COLON = ":";@Value("${spring.mongo.mongoDatabaseAddress}")private String mongoDatabaseAddress;@Value("${ername}")private String username;@Value("${spring.mongo.dbname}")private String dbname;@Value("${spring.mongo.password}")private String password;@Value("${spring.mongo.connectionsPerHost}")private String connectionsPerHost;/*** 获取mongodb的地址** @return*/private List<ServerAddress> getMongoDbAddress() {List<ServerAddress> serverAddrList = new ArrayList<ServerAddress>();//如果有多个服务器的话if (this.mongoDatabaseAddress.indexOf(COMMA) > 0) {String[] addressArrays = mongoDatabaseAddress.split(COMMA);String[] hostPort;for (String address : addressArrays) {hostPort = address.split(COLON);ServerAddress serverAdress = new ServerAddress(hostPort[0], Integer.valueOf(hostPort[1]));serverAddrList.add(serverAdress);}} else {String[] hostPort = mongoDatabaseAddress.split(COLON);ServerAddress serverAdress = new ServerAddress(hostPort[0], Integer.valueOf(hostPort[1]));serverAddrList.add(serverAdress);}return serverAddrList;}/*** 设置连接参数*/private MongoClientOptions getMongoClientOptions() {MongoClientOptions.Builder builder = MongoClientOptions.builder();// todo 添加其他参数配置//最⼤连接数builder.connectionsPerHost(Integer.valueOf(connectionsPerHost));MongoClientOptions options = builder.readPreference(ReadPreference.nearest()).build();return options;}/**** @return*/@Beanpublic MongoClient mongoClient() {//使⽤数据库名、⽤户名密码登录MongoCredential credential = MongoCredential.createCredential(username, dbname, password.toCharArray());//创建Mongo客户端return new MongoClient(getMongoDbAddress(), credential, getMongoClientOptions());}/*** 注册mongodb操作类* @param mongoClient* @return*/@Bean@ConditionalOnClass(MongoClient.class)public MongoTemplate mongoTemplate(MongoClient mongoClient) {MongoTemplate mongoTemplate = new MongoTemplate(new SimpleMongoDbFactory(mongoClient, dbname));return mongoTemplate;}}mongoDB操作使⽤MongoTemplate类进⾏增删改查@Servicepublic class MongodbService {@Autowiredprivate MongoTemplate mongoTemplate;/*** 新增⽂档** @param userDTO* @return*/public UserDTO insert(UserDTO userDTO) {//insert⽅法并不提供级联类的保存,所以级联类需要先⾃⼰先保存return mongoTemplate.insert(userDTO);}public UserDTO save(UserDTO userDTO) {Sort sort = new Sort(Sort.Direction.DESC, "name");userDTO = mongoTemplate.findOne(Query.query(Criteria.where("")).with(sort), UserDTO.class);return mongoTemplate.save(userDTO);}/*** 删除⽂档* NOTE:remove⽅法不⽀持级联删除所以要单独删除⼦数据* @param name*/public void remove(String name) {//根据名字查询数据并删除UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)), UserDTO.class);//remove⽅法不⽀持级联删除所以要单独删除⼦数据List<AddressDTO> addressList = userDTO.getAddressList();for (AddressDTO addressDTO : addressList) {mongoTemplate.remove(addressDTO);}//删除主数据mongoTemplate.remove(userDTO);}/*** 更新⽂档* @param userDTO*/public void update(UserDTO userDTO) {mongoTemplate.updateFirst(Query.query(Criteria.where("name").is(userDTO.getName())), Update.update("age", userDTO.getAge()), UserDTO.cl ass);}/*** 查询⽂档* @param name*/public void find(String name) {Sort sort = new Sort(Sort.Direction.DESC, "name");List<UserDTO> userDTOS = mongoTemplate.find(Query.query(Criteria.where("name").is(name)), UserDTO.class);//基于sort排序使⽤findOne查询最新⼀条记录UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)).with(sort), UserDTO.class);//模糊查询List<UserDTO> userDTOList = mongoTemplate.find(Query.query(Criteria.where("name").is(name).regex(name)).with(sort), UserDTO.class);//分页查询Pageable pageable = PageRequest.of(3, 20, sort);List<UserDTO> userDTOPageableList = mongoTemplate.find(Query.query(Criteria.where("name").is(name)).with(pageable), UserDTO.class);//总数long conut = mongoTemplate.count(Query.query(Criteria.where("name").is(name)), UserDTO.class);Page<UserDTO> page = new PageImpl(userDTOPageableList, pageable, conut);}}NOTE: 在开发中,如果从任何MongoDB操作返回的com.mongodb.WriteResult包含错误,则可以⽅便地记录或引发异常。

Mongodb系列-spring-data-mongodb使用MongoTemplate实。。。

Mongodb系列-spring-data-mongodb使用MongoTemplate实。。。

Mongodb系列-spring-data-mongodb使⽤MongoTemplate实。

在⽤spring-data-mongodb框架开发的过程中,需要实现分页查询,就百度了下,没找到满意的⼜google了下,找到了思路.在spring-data-mongodb 官⽅⽂档中,建议你使⽤PagingAndSortingRepository 来实现分页,但是我是真的不喜欢这个设计啊!!⽤⽅法名来映射查询语句,框架会⾃动⽣成执⾏代码,还为此定义了⼀套语法,举个例⼦:public interface UserRepository extends MongoRepository<User, String>, QueryDslPredicateExecutor<User> {@Query("{ 'name' : ?0 }")List<User> findUsersByName(String name);@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }")List<User> findUsersByAgeBetween(int ageGT, int ageLT);List<User> findByName(String name);List<User> findByNameLikeOrderByAgeAsc(String name);List<User> findByAgeBetween(int ageGT, int ageLT);@Query(value = "{}", fields = "{name : 1}")List<User> findNameAndId();@Query(value = "{}", fields = "{_id : 0}")List<User> findNameAndAgeExcludeId();}这个接⼝类只定义了接⼝,并不需要实现,因为SDM框架(spring-data-mongodb简称,以下都使⽤简称)会帮你⽣成代码..findByAgeBetween(int ageGT, int ageLT);-> 就是where ageGT <age and age <ageLT;刚开始可能感觉很简单,但是⼀旦字段多了查询条件复杂了! 你根本不知道⾃⼰在写什么!别⼈看你的代码⼀长串⽅法名,也是直接懵逼的..⽽查出来的许多分页查询也是直接使⽤的PagingAndSortingRepository 这个接⼝,⾃动⽣成...⾮常不喜欢...就去查怎么使⽤MongoTemplate实现...先下班....放假回来补上..哈哈庆祝五⼀上班,把没写的写完...使⽤MongoTemplate实现分页@Repository("deviceStatusRepository")public class DeviceStatusRepository {@Autowiredprivate MongoOperations mongoOperations;/*** 分页查询*/public PageImpl<DeviceStatusItem> pageDeviceStatusItemByDeviceSerial(String deviceSerial, String collectionName,int pageIndex, int pageSize) {Query query = Query.query(Criteria.where(CONSTS.DEVICE_SERIAL_FIELD).is(deviceSerial));// 每页五个Pageable pageable = new PageRequest(pageIndex, pageSize); // get 5 profiles on a pagequery.with(pageable);// 排序query.with(new Sort(Direction.ASC, CONSTS.DEVICE_SERIAL_FIELD, CONSTS.DOMAINID_FIELD));// 查询总数int count = (int) mongoOperations.count(query, DeviceStatusItem.class, collectionName);List<DeviceStatusItem> items = mongoOperations.find(query, DeviceStatusItem.class, collectionName);// System.out.println("stories:" + stories.size() + " count:" + count);return (PageImpl<DeviceStatusItem>) PageableExecutionUtils.getPage(items, pageable, () -> count);}}解析:MongoOperations 是MongoTemplate的接⼝,它的具体实现就是MongoTemplate,所以这⾥使⽤MongoTemplate或MongoOperations 都可以.1. 创建PageRequest 对象,这是SDM框架提供的现成的分页请求类.构造函数很简单:// page:第⼏页, size:每页的⼤⼩public PageRequest(int page, int size) {this(page, size, null);}2. 构建Query 查询条件.我这⾥先是指定了根据序列号查询,然后设置分页请求 query.with(pageable);最后设置结果的排序.3. 使⽤SDM框架⾃带的⼯具类PageableExecutionUtils 返回PageImpl .这⾥的PageableExecutionUtils 和PageImpl 其实都可以⾃⼰实现,你可以打开PageImpl 看⼀下代码很简单,就是对查询结果封装了下,⽅便数据的返回.调⽤⽅法:1// 序列号2 String deviceSerial="123456";3//集合的名字,就相当于表名4 String cllectionName="device";5//返回第⼏页6int pageIndex = 0;7//每页的⼤⼩8int pageSize = 10;9 PageImpl<DeviceStatusItem> pageImpl = deviceStatusRepository10 .pageDeviceStatusItemByDeviceSerial(deviceSerial, collectionName, pageIndex, pageSize);11 System.out.println("list:" + pageImpl.getContent() + " number:" + pageImpl.getNumber() + " size:"12 + pageImpl.getSize() + " pages:" + pageImpl.getTotalPages()13 + " TotalElements:" + pageImpl.getTotalElements());解析: 这个PageImpl ⽅法名很清晰了.查询的结果集: pageImpl.getContent(),当前页是第⼏个: pageImpl.getNumber()当前页的⼤⼩: pageImpl.getSize()⼀共多少页: pageImpl.getTotalPages()⼀共多少条记录: pageImpl.getTotalElements()优化的分页实现使⽤上边的分页实现没有⼤的问题, 但是有⼀个性能问题, 当你的集合很⼤的时候, count每次执⾏都会全表扫描⼀下,因为你只有全表扫描才知道有多少数量,耗费很多时间.⽽这个时间是没有必要的.你优化的实现就是去掉count,就想下边这样:/*** deviceSerials分页查询,不使⽤count,不然每次都要全表扫描.*/public PageImpl<DeviceStatusItem> pageDeviceStatusItemByDeviceSerialListNotCount(List<String> deviceSerials,String collectionName, int pageIndex, int pageSize) {Query query = Query.query(Criteria.where(CONSTS.DEVICE_SERIAL_FIELD).in(deviceSerials));// 每页五个Pageable pageable = new PageRequest(pageIndex, pageSize); // get 5 profiles on a pagequery.with(pageable);// 排序query.with(new Sort(Direction.ASC, CONSTS.DEVICE_SERIAL_FIELD, CONSTS.DOMAINID_FIELD));List<DeviceStatusItem> items = readMongoTemplate.find(query, DeviceStatusItem.class, collectionName);// System.out.println("stories:" + stories.size() + " count:" + count);return (PageImpl<DeviceStatusItem>) PageableExecutionUtils.getPage(items, pageable, () -> 0);}把count去掉就好.这样去掉count后, 只有在最后⼀次查询时才会进⾏全表扫描.使⽤count和不使⽤count性能⽐较1.准备数据:准备了50万数据,不是很多,就简单测试下, 数据量越⼤效果越明显.2.测试程序只列了主要的程序:public static void readUseCount(IDeviceShadowQueryService deviceShadowQueryService, List<String> deviceSerials) { int pageIndex = 0;int pageSize = 80;int totalPages = 0;Pagination<DeviceStatusDto> pagination = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerials(deviceSerials, pageIndex, pageSize);int size = pagination.getRecords().size();totalPages = pagination.getTotalPages();// 第1页开始for (int i = 1; i < totalPages; i++) {pagination = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerials(deviceSerials, i, pageSize);totalPages = pagination.getTotalPages();size = pagination.getRecords().size();}count++;if (count % 100 == 0)System.out.println("totalPages:" + totalPages + " size:" + size);}public static void readNoCount(IDeviceShadowQueryService deviceShadowQueryService, List<String> deviceSerials) { int pageIndex = 0;int pageSize = 80;Pagination<DeviceStatusDto> page = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerialsList(deviceSerials, pageIndex, pageSize);int size = page.getRecords().size();while (size == pageSize) {pageIndex++;page = deviceShadowQueryService.readDeviceStatusDtoByDeviceSerialsList(deviceSerials, pageIndex, pageSize); size = page.getRecords().size();}count++;if (count % 100 == 0)System.out.println("pageIndex:" + pageIndex + " size:" + size);}3.测试结果使⽤count,开始读取, ⼤⼩:99975使⽤count,读取完毕,⼤⼩:99975 花费时间:112792不使⽤count,读取完毕,⼤⼩:99975 花费时间:109696不使⽤count,节约时间: 112792-109696=2900= 2.9s参考:。

springdatamongodb操作

springdatamongodb操作

springdatamongodb操作xml配置(mongo集群⽅式):<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:mongo="/schema/data/mongo"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/context/schema/context/spring-context-3.0.xsd/schema/data/mongo/schema/data/mongo/spring-mongo.xsd"><!--credentials的配置形式是:⽤户名:密码@默认数据库--><!-- credentials="${ername}:${mongo.password}@${mongo.dbname}" --><mongo:mongo-client id="mongoClient" replica-set="${mongo.replica.set.address}"><mongo:client-optionsconnections-per-host="${mongo.connections_per_host}"threads-allowed-to-block-for-connection-multiplier="${mongo.threads_allowed_to_block_for_connection_multiplier}" connect-timeout="${mongo.connect_timeout}"max-wait-time="${mongo.max_wait_time}"socket-timeout="${mongo.socket_timeout}"/></mongo:mongo-client><mongo:db-factory id="mongoDbFactory" dbname="${mongo.dbname}" mongo-ref="mongoClient" /><!--⾸先列⼀下WriteConcern的⼏种抛出异常的级别参数:WriteConcern.NONE:没有异常抛出WriteConcern.NORMAL:仅抛出⽹络错误异常,没有服务器错误异常WriteConcern.SAFE:抛出⽹络错误异常、服务器错误异常;并等待服务器完成写操作。

springdatamongodb五:进阶文档查询(分页morphia)(二)

springdatamongodb五:进阶文档查询(分页morphia)(二)

springdatamongodb五:进阶文档查询(分页morphia)(二)
Spring Data MongoDB 三:基本文档查询(Query、BasicQuery)(一)
学习MongoDB 六:MongoDB查询(游标操作、游标信息)(三)
一.简介
SpringData MongoDB提供了
org.springframework.data.mongodb.core.MongoTemplate对MongoDB的find的操作,我们上一篇介绍了基本文档的查询,我们今天介绍分页查询,分页查询是返回到匹配文档的游标,可以随意修改查询限制、跳跃、和排序顺序的功能。

我们在查询时find()方法接受Query类型有
org.springframework.data.mongodb.core.query和
org.springframework.data.mongodb.core.query.BasicQuery Query类提供方法有limit、skip、sort查询限制、跳跃、和排序顺序的功能,BasicQuery继承了Query类。

Query
Mongodb
说明Query limit (int limit)
limit
方法是限制游标返回结果的数量Query skip (int skip)
skip
方法可以跳过指定值的条数,返回剩下的条数的结果,可以跟limit()方法进行组合可以实现分页的效果Sort sort () 已过时
现在是用query.with(sort)
sort
方法来对数据进行排序,根据指定的字段,并使用1或-1来指定排序方式是升序或降序,类似于SQL的order by。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Spring-data-mongodb使用手册文档信息(Document Info)标题(Title)Spring-data-mongodb使用手册文档编号(No)2012-09-19作者(Author)张瑜最后发布时间(Last Update)2012-09-20概述(Summarize)安装mongodb以及掌握spring-data-mongodb的使用方法,一些最佳实践修订信息(Revise Info)修订日期(Date)修订人(Reviser) 修订内容(Revises)附件信息(Attachment Info)目录文档信息(Document Info) (2)修订信息(Revise Info) (3)附件信息(Attachment Info) (4)1.概述 (5)1.1.目的 (5)1.2.范围 (6)2.准备 (6)2.1.环境配置 (6)2.2.Windows7安装mongodb (6)2.2.1.配置环境变量 (6)2.2.2.启动配置mongodb (7)3.Spring-data-mongodb (8)3.1.背景 (8)3.1.1.高级API (9)3.1.2.低级API (9)3.2.MongoDbFactory (9)3.3.MongoTemplate (9)3.4.Operations (10)3.4.1.常用Api的方法: (10)3.5.项目中如何配置实用mongodb (11)3.6.Callback .................................................................................. 错误!未定义书签。

3.7.Topic和Messaging/PubSub (14)3.8.Cache (14)4.NoSQL数据库设计 (14)4.1.案例1 (14)5.最佳实践 (14)5.1.项目案例1(Tinybee项目) (14)1.概述1.1. 目的让团队成员比较快的上手mongodb的相关功能,思考如何结合自己的项目使用。

1.2. 范围所有工程师。

2.准备mongodb 下载地址:/downloadsmongodb 官方文档下载地址:/docs/mongodb-docs-2012-09-19.pdf十天精通mongodb 下载地址(强烈建议看下,其中包含对mongodb的详细介绍):/file/id_45545890496119199.htm如果你对mongodb希望有更多的了解(其中为mongodb资料专题):/html/3548.htmlmongodb管理工具下载地址:/file/id_45545890496119201.htm2.1. 环境配置在这里提供针对windows7 系统的配置方案2.2. Windows7安装mongodbmongodb及其管理工具下载地址参见准备章节!mongodb启动命令参数详见:/jacky0525/blog/330482.2.1.配置环境变量1、在系统环境变量中添加MONGODB_HOME如图所示:2、在PA TH中添加%MONGODB_HOME%\bin 如图所示:在mongodb 目录中新建data 和log 文件夹(为启动时做准备)2.2.2.启动配置mongodb进入DOS命令窗口输入一下命令:mongod --dbpath D:\mongodb\data --logpath D:\mongodb\log --logappend --directoryperdb--dbpath数据库安装目录--logpath 数据库输出目录--logappend 日志追加,默认为覆盖--directoryperdb 表示每个db一个目录执行命令之后开启新的DOS窗口执行mongo 输出表示启动成功。

目前是以无权限限制的方式启动的,你可以做任何操作。

现在我们需要切换到admin下,创建一个root用户。

执行命令:show dbs 显示所有dbuse admin 使用admin dbdb 显示当前使用的dbdb.addUser(”root”,”root”); 添加用户,用户名为root 密码为rootdb.auth(”root”,”root”); 为用户授权这样我们就为admin db创建好用户,接下来以权限限制方式启动mongodb(记得关掉之前开启的服务),执行命令(在之前启动命令中添加参数-auth即可):mongod --dbpath D:\mongodb\data --logpath D:\mongodb\log --logappend --auth–directoryperdb-auth 安全模式下运行接下来使用之前授权的用户名密码登录,打开新的DOS命令窗口输入如下命令:mongo 数据库名称–u 用户名–p 密码mongo admin –u root –p root注意:为了启动方便可以把mongodb加入windows系统service以管理员身份打开DOS命令窗口键入如下命令:mongod --dbpath D:\mongodb\data --logpath D:\mongodb\log --logappend --auth--directoryperdb –install这时候会在系统服务中增加mongo db 项第一次配置完成后,一定要重启才会有效果重启mongo客户端,不输入-u-p可以直接进入,但是不具有任何权限。

3.Spring-data-mongodb3.1. 背景SQL or NoSQL?That’s a question! SQL 与NoSQL 的争论从来没有停息过,但其实任何一种技术都不会是适合一切应用场景的,重要的是你要充分了解自己的需求,再充分了解你要选择的技术的优劣。

优势:快速!(当然,这和具体的应用方式有关,通常来说,它比一般的关系型数据库快5位左右。

)很高的可扩展性–轻轻松松就可实现PB级的存储(但是可能我们并不需要PB级的存储,10TB可能就够了)他有一个很好的replication 模式(replica sets)有很完善的Java API他的存储格式是Json的,这对Java来说非常好处理,对javascirpt亦然。

运维起来非常方便,你不用专门为它安排一个管理员。

它有一个非常活跃的社区。

他的版本控制非常清楚。

MongoDB 背后的公司(10gen)已经准备好了明天在MongoDB 上面的投入的资金。

劣势:应用经验缺乏,我们都没有相关NoSQL 产品的使用经验。

项目相对来说还比较新。

和以往的存储相比,数据的关系性操作不再存在。

常用Jar:spring-data-mongodbmongo-java-driverspring-core相关JAR在MA VEN包管理中搜索选择对应版本即可3.1.1.高级API3.1.2.低级API3.2. MongoDbFactory就像所有的数据库连接,mongoDbFactory就是连接工厂,通过配置单台服务器或者连接池(pool)的方式获取Mongodb服务器的连接。

3.3. MongoTemplate就像Spring提供的JDBC,hibernate和ibatis的template一样,spring-data-mongodb 也提供了一个基础的泛型MongoTemplate供开发者可以快速的利用代码完成基础的crud工作。

在实践中可以考虑完全省去dao层的设计,直接在service层注入相应的template实例。

在此推荐写一个Repository<T>接口其中提供对mongodb的CRUD操作。

3.4. Operations其实所有的操作都是直接映射Mongodb本身提供的命令行,Spring-data-mongodb 文档来操作。

官网提供的API Javadoc有问题报404,只能看HTML版的参考手册:/spring-data/data-mongodb/docs/current/reference/html/ 404问题修复了(官方API):/spring-data/data-mongodb/docs/current/apidocs/3.4.1.常用Api的方法:新增方法:User user = new User("...");//将user对象保存到"user"这个collection中mongoTemplate.save(user);//将user对象保存到"new collection"这个collection中mongoTemplate.save("new collection",user);//将user对象保存到"user"这个collection中mongoTemplate.insert(user);//将user对象保存到"new collection"这个collection中mongoTemplate.insert("new collection", user);//将user的对象列表(List)保存到"user"collection中去mongoTemplate.insertList(userInList);//将user的对象列表(List)保存到"new collection"collection中去mongoTemplate.insertList("new collection", userInList);另外请注意其中的save和insert的区别。

它们的区别为:1)save意思是,当记录不存在时插入,或者是当记录已存在是更新,实际上就是save or update的意思。

2) insert的意思是:当记录不存在时插入,而如果记录存在时则忽略,继续插入。

查询方法://创建查询条件id = 123 和name = zhangyuQuery query = new Query(Criteria.where("id").is(123).and("name").is("zhangyu"));//执行查询返回结果List<User> user = mongoTemplate.find(query, User.class);//创建查询条件id <= 123 和name = zhangyuQuery query = new Query(Criteria.where("id").lte(123).and("name").is("zhangyu"));删除方法:User user = new User("...");//删除user集合中的user对象mongoOperation.remove(user);//删除test集合下的id=2的user对象mongoOperation.remove("test", new Query(Criteria.where("id").is("2")));//删除test集合下的,id=3的user对象,最后并且返回这个被删除的对象User deletedUser = mongoOperation.findAndRemove("test",new Query(Criteria.where("id").is("3")), User.class);3.5. 项目中如何配置实用mongodb配置文件如图所示:之后通过注解注入mongoTemplate 即可3.6. 基于实体Bean操作1、使用@Document注解指明一个领域对象将被持久化到MongoDB中。

相关文档
最新文档