MongoTemplate

MongoTemplate

MongoDB目前3大核心优势:『灵活模式』+ 『高可用性』 + 『可扩展性』,通过json文档来实现灵活模式,通过复制集来保证高可用,通过Sharded cluster来保证可扩展性。



一、MongoDB是什么?

介绍:MongoDB是一款文档型NOSQL(Not Only SQL)数据库,其支持水平扩展,通过其提供的 shard 和 copy 机制可以比较容易的应对大数据量的业务场景。对于 Spring 而言,其通过 Spring Data MongoDB 提供了和 MongoDB 交互的相关API

Mongo的优势:

  1. 它会把数据文件映射到内存中,如果是读操作,内存中的数据起到缓存的作用,如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。MongoDB并不干涉内存管理工作,而是把这些工作留给操作系统的虚拟内存管理器去处理,这样做的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,幸运的是虚拟内存管理器的存在让我们多数时候并不需要关心这个问题。
  2. MongoDB的内存使用机制让它在缓存重建方面更有优势,简而言之:如果重启进程,那么缓存依然有效

相关链接

官方链接
api链接
文档链接
大佬


Criteria条件查询
MongoTemplate中 i n 、 in、 ingt、 a d d T o S e t 、 addToSet、 addToSetelemMatch、排序、分页的使用

二、使用步骤

1.准备

配置
MongoTemplate基于​spring-data-mongo支持,springboot项目中引入核心依赖

<!--mongo-->
         <!-- spring Mongo配置 包 -->
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>mongodb-plus-spring-boot-starter</artifactId>
            <version>1.0.0.RELEASE</version>
        </dependency>
         <!-- springData Mongo 使用包 -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>

application.yml

spring:
  data:
    mongodb:
       uri: mongodb://<username>:<password>@47.93.35.143:27017/test

Mongo配置详情:

#mongo配置
#mongo服务的端口号
spring.data.mongodb.port=27017
#mongo服务的地址
spring.data.mongodb.host=xxxxxx
#mongo服务的登录名称
spring.data.mongodb.username=xxxxx
#mongo服务的密码
spring.data.mongodb.password=xxxxxxx
#此人的验证数据库
spring.data.mongodb.authentication-database=xxxxxxxx
#待连接数据库
spring.data.mongodb.database=xxxxxxxx
#mongo最大的池子数
spring.data.mongodb.option.max-connection-per-host=100
#设置允许阻塞等待连接的线程数的乘数。
spring.data.mongodb.option.threads-allowed-to-block-for-connection-multiplier=5
#套接字选择超时时间
spring.data.mongodb.option.server-selection-timeout=30000
#最大等待时间
spring.data.mongodb.option.max-wait-time=120000
#池化连接的最大空闲时间。零值表示空闲时间没有限制。超出其空闲时间的池化连接将被关闭,并在必要时由新连接替换。
spring.data.mongodb.option.max-connection-idle-time=300000
#服务器断开时间
spring.data.mongodb.option.max-connection-idle-time=300000
#连接超时实际那
spring.data.mongodb.option.connect-timeout=10000
# 设置套接字超时
spring.data.mongodb.option.socket-timeout=0
#会话一直存在的会引发socket异常
spring.data.mongodb.option.socket-keep-alive=false
#设置启用SSL
spring.data.mongodb.option.ssl-enabled=false
#定义是否允许使用无效的主机名。
spring.data.mongodb.option.ssl-invalid-host-name-allowed=false
#设置驱动程序注册的JMX bean是否应始终为MBean,无论VM是Java还是更高版本。
spring.data.mongodb.option.always-use-m-beans=false
#设置用于群集心跳的连接的套接字超时。
spring.data.mongodb.option.heartbeat-socket-timeout=20000
#设置用于群集心跳的连接的连接超时。
spring.data.mongodb.option.heartbeat-connect-timeout=20000
#设置最小心跳频率。如果驱动程序必须经常重新检查服务器的可用性,它将至少在上一次检查后等待很长时间,以避免浪费精力。默认值为500毫秒。
spring.data.mongodb.option.min-heartbeat-frequency=500
#设置心跳频率。这是驱动程序将尝试确定群集中每个服务器的当前状态的频率。默认值为10,000毫秒
spring.data.mongodb.option.heartbeat-frequency=10000
#可配置默认值为15毫秒
spring.data.mongodb.option.local-threshold=15

2.使用介绍

Mongo中Query和Criteria的联系

一、定义

Query是查询类,对mongo查询时通常需要用到该类

Criteria是条件类,封装了一系列的条件方法,比如准确查询方法,模糊查询方法,比较查询方法

二、使用

Query和Criteria的关系比较灵活,有很多使用方法

1.Criteria使用where的形式

Query query = new Query();
query.addCriteria(Criteria.where("name").is("张三"));

2.Criteria创建对象使用and形式

Query query = new Query();
Criteria criteria = new Criteria();
criteria.and("name").is("张三");
criteria.and("sex").is("男");
query.addCriteria(criteria);

3.也可以在query.addCriteria()内

Query query = new Query();
Criteria criteria = new Criteria();
query.addCriteria(criteria.and("name").is("张三"));
query.addCriteria(criteria.and("sex").is("男"));

或者

query.addCriteria(Criteria.where("name").is("张三"));
query.addCriteria(Criteria.where("sex").is("男"));

(1)查询

简单条件查询:BasicDBObject来封装

复杂条件查询:Query query用来封装查询条件

(1)查询全部=====db.集合名.find()

mongoTemplate.findAll(Class<T> entityClass, String collectionName) 

(2)查询符合条件中的第一条=====db.集合名.findOne(条件)

mongoTemplate.findOne(Query query, Class<T> entityClass, String collectionName)

(3)带条件查询=====db.集合名.find(条件)

mongoTemplate.find(Query query, Class<T> entityClass, String collectionName)

Query使用

1、创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
2、精准条件:criteria.and(“key”).is(“条件”)
模糊条件:criteria.and(“key”).regex(“条件”)
3、封装条件:query.addCriteria(criteria)
4、大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)

5、Query.addCriteria(new Criteria().andOperator(gt,lt));

6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。

7、排序 :query.with(new Sort(Sort.Direction.ASC, “age”). and(new Sort(Sort.Direction.DESC, “date”)))

实例:

mongoTemplate.find(query, FormDataApproval.class, "formDataApproval");
mongoTemplate.findOne(query, FormDataApproval.class, "formDataApproval");
mongoTemplate.findAll(FormDataApproval.class, "formDataApproval");
mongoTemplate.findById(formDataApproval.getId(), FormDataApproval.class, "formDataApproval");
查询高级
准确查询:使用关键词“is”
Query query = new Query();
query.addCriteria(Criteria.where("name").is("张三"));

多条件查询:

Query query = new Query();
query.addCriteria(Criteria.where("name").is(name));
query.addCriteria(Criteria.where("age").is(age));
模糊查询:使用关键词“regex”,内为正则表达式

方法1:

Query query = new Query();
String name = "张三";
query.addCriteria(Criteria.where("name").regex(".*?\\" +name+ ".*"));

方法2:

Pattern pattern=Pattern.compile("^.*"+pattern_name+".*$", Pattern.CASE_INSENSITIVE);
query.addCriteria(Criteria.where("name").regex(pattern))
比较查询:使用关键词“gt”/“gte”/“lt”/“lte”

Query query = new Query();
query.addCriteria(Criteria.where(“createTime”).gte(开始时间).lte(结束时间));

关联查询
LookupOperation lookupToLots = LookupOperation.newLookup().
            from("eCostRecord").//关联表名 lots
            localField("lsumpDocNumber").//关联字段
            foreignField("lsumpDocNumber").//主表关联字段对应的次表字段
            as("groups");//查询结果集合名    
//主表
Criteria ordercri = Criteria.where("eccDocNo").ne(null).ne("");
AggregationOperation match = Aggregation.match(ordercri);
//次表
Criteria ordercri1 = Criteria.where("group").is(true);
AggregationOperation match1 = Aggregation.match(ordercri);
 
//UnwindOperation unwind = Aggregation.unwind("groups");
Aggregation aggregation = Aggregation.newAggregation(match,  lookupToLots,match1//, unwind);
 
return mongoTemplate.aggregate(aggregation, "reClassGroup", ReClassGroup.class).getMappedResults();

聚合查询

mongoTemplate.aggregate()聚合查询

包含某些数据的list查询
详解MongoDB中的多表关联查询($lookup)
Spring Data Mongodb多表关联查询
SpringBoot整合MongoDB实现聚合查询(多表联查)以及一套简单CRUD
springboot操作MongoDB增删改查以及多表聚合查询

(2)新增

MongoTemplate实现了MongoOperations接口

1、mongoTemplate.insert()-------------(MongoTemplate中)
2、mongoTemplate.save()--------------(MongoOperations中)

区别
insert: 若新增数据的主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常提示主键重复,不保存当前数据。
save: 若新增数据的主键已经存在,则会对当前已经存在的数据进行修改操作。
insert: 可以一次性插入一整个列表,而不用进行遍历操作,效率相对较高
save: 需要遍历列表,进行一个个的插入。

实例:

mongoTemplate.save(formDataApproval, "formDataApproval"); // 同upsert(),没有新增,有修改
mongoTemplate.insert(formDataApproval, "formDataApproval");
mongoTemplate.insertAll(list);

(3)删除

mongoTemplate.remove(Query query,Class entityClass)

实例:

mongoTemplate.remove(query, FormDataApproval.class, "formDataApproval");
mongoTemplate.findAndRemove(query, FormDataApproval.class, "formDataApproval");
mongoTemplate.findAllAndRemove(query, FormDataApproval.class, "formDataApproval");

(4)修改

Update update = Update.update(“要更新的字段”, “更新的值”);

1、方式一
//数据库有,就新增, 没有,就修改
mongoTemplate.upsert(query, update, Class entityClass);

2、方式二

更新满足条件的第一条数据

mongoTemplate.updateFirst(query, update, Class entityClass);

更新所有满足条件的数据

mongoTemplate.updateMulti(query, update, Class entityClass);
MongodbTemplate的增删改操作
实例:

  mongoTemplate.upsert(query, update, FormData.class, "formData");

  mongoTemplate.update(FormDataApproval.class);
  mongoTemplate.updateFirst(query, update, FormDataApproval.class, "formDataApproval");
  mongoTemplate.updateMulti(query, update, FormDataApproval.class, "formDataApproval");
  mongoTemplate.findAndModify(query, update, FormDataApproval.class, "formDataApproval");

(5)其他

MongoDB批量更新和批量插入的方式

排序

1.升序

Query query = new Query();

query.with(Sort.by(Sort.Order.asc(“name”))); //name是表中的某个字段

2.降序

Query query = new Query();

query.with(Sort.by(Sort.Order.desc(“name”)));

  • 如何实现场景1
  • 如何实现场景2
分页时查找数量
public long countSample(String id) {
    Query query = new Query();
    if (StringUtil.hasText(id))
       query.addCriteria(Criteria.where("creator").is(id));
    return mongoTemplate.count(query, Sample.class);
}
分页
public List<Sample> searchAllSample(String id, PageTag page) {
   Query query = new Query();
   query.with(new Sort(new Sort.Order(Sort.Direction.DESC, "update_date")));
   int skip = (page.getCurrentPage() - 1) * page.getPageSize();
   if (StringUtil.hasText(id)) {
       Criteria criteria = Criteria.where("creator").is(id);
       query.addCriteria(criteria);
   }
   query.skip(skip);// 从那条记录开始
   query.limit(page.getPageSize());// 取多少条记录
   return mongoTemplate.find(query, Sample.class);
}
   public List<PersonDO> test(String id, Integer page) {
        Query query = new Query();
        if (!EmptyUtil.isEmpty(id)) {
            Criteria criteria = Criteria.where("_id").gt(new ObjectId(id));
            query.addCriteria(criteria);
        }
        
        query.limit(page);// 取多少条记录
        return this.find(query, MongoCollectionName.BC_PERSON);
    }
修改数量
public void modifyHitNumByNo(String no) {
   Query query = new Query();
   query.addCriteria(Criteria.where("sap_no").is(no));
   Update update = new Update();
   update.inc("hit_num", 1);
   mongoTemplate.updateFirst(query, update, Project.class);
}
模糊查询
public List<Sample> findSamples(String memberId, SelectVo selectVo) {
   Criteria criteria = Criteria.where("creator").is(memberId);
   if (StringUtil.hasText(selectVo.getName())) {
       Pattern pattern = Pattern.compile("^.*" + selectVo.getName() + ".*$", Pattern.CASE_INSENSITIVE);
       criteria.orOperator(Criteria.where("projectNo").regex(pattern), Criteria.where("name").regex(pattern));
   }
   return findPageList(Query.query(criteria), Sample.class, new PageTag(selectVo.getPage(), selectVo.getPageSize()));
}
一个模糊关键字匹配多字段
 Pattern pattern=Pattern.compile("^.*"+pattern_name+".*$", Pattern.CASE_INSENSITIVE);
            criatira.orOperator(Criteria.where("name").regex(pattern),
                    Criteria.where("sex").regex(pattern),
                    Criteria.where("age").regex(pattern),
                    Criteria.where("class").regex(pattern));

假设我们有四个查询条件,criteria是主查询criteria。
Criteria criteria= new Criteria();
Criteria criteriaA= new Criteria();
Criteria criteriaB= new Criteria();
Criteria criteriaC= new Criteria();
Criteria criteriaD= new Criteria();

1.andOperator:

 criteria.andOperator(criteriaA,criteriaB,criteriaC,criteriaD);

2.orOperator:

2.1 情况一
如果是针对同样的字段进行or。则可以使用:

criteria.orOperator(criteriaA,criteriaB,criteriaC,criteriaD);

例如:

Criteria c1= Criteria.where("year").gte(startYear).lte(endYear).and("month").is(endMonth).and("day").gte(startDay).lte(endDay)  
            .and("hour").gte(startHour).lte(endHour).and("minute").is(startMinute).and("second").gte(startSecond);  
Criteria c2=Criteria.where("year").gte(startYear).lte(endYear).and("month").is(endMonth).and("day").gte(startDay).lte(endDay)  
            .and("hour").gte(startHour).lte(endHour).and("minute").is(endMinute).and("second").lte(endSecond);  
Criteria c3 =Criteria.where("year").gte(startYear).lte(endYear).and("month").is(endMonth).and("day").gte(startDay).lte(endDay)  
            .and("hour").gte(startHour).lte(endHour).and("minute").gt(startMinute).lt(endMinute);  
Criteria cr = new Criteria();  
  
query = new Query(cr.orOperator(c1,c2,c3));  
                  
getMongoTemplate().find(query, SensorCollection.class);

2.2 情况二

如果针对的是不同的字段,几个字段之间是or 但是 分成几组情况,每组必须满足其中一个条件。
这种情况需要使用andOperator把多个orOperator连接起来。每个orOperator是一组情况。
如下:

Criteria criteria = new Criteria();
		MapSafeGetter param = new MapSafeGetter(req.getSearch());
		Criteria criteriaSearch = new Criteria();
		if (!StringUtils.isEmpty(param.getString("searchValue"))) {
			criteriaSearch.orOperator(Criteria.where("orderId").is(param.getString("searchValue")),
					Criteria.where("productName").regex(".*?" + param.getString("searchValue") + ".*"),
					Criteria.where("coupon").regex(".*?" + param.getString("searchValue") + ".*"),
					Criteria.where("receiver").regex(".*?" + param.getString("searchValue") + ".*"),
					Criteria.where("mobile").is(param.getString("searchValue")),
					Criteria.where("reason").regex(".*?" + param.getString("searchValue") + ".*"));
		}
		if (!StringUtils.isEmpty(param.getString("productId"))) {
			criteria.and("productId").is(param.getString("productId"));
		}
		
		
		criteria.and("dealed").is(false);
		criteria.and("invalid").ne(true);
		Criteria criteriaOk = new Criteria();
		criteriaOk.orOperator(
				Criteria.where("backReceived").ne(true),
				Criteria.where("approved").ne(true)
				);

		
		Criteria criteriaTime = new Criteria();
		if (!StringUtils.isEmpty(param.getString("beginTime")) || !StringUtils.isEmpty(param.getString("endTime"))) {
			Criteria criteriaApplyTime = new Criteria();
			criteriaApplyTime = criteriaApplyTime.and("applyTime");
			Criteria criteriaDealTime = new Criteria();
			criteriaDealTime = criteriaDealTime.and("dealTime");

			if (!StringUtils.isEmpty(param.getString("beginTime"))) {
				criteriaApplyTime.gte(DateUtils.parse(param.getString("beginTime")));
				criteriaDealTime.gte(DateUtils.parse(param.getString("beginTime")));
			}
			if (!StringUtils.isEmpty(param.getString("endTime"))) {
				criteriaApplyTime.lte(DateUtils.parse(param.getString("endTime")));
				criteriaDealTime.lte(DateUtils.parse(param.getString("endTime")));
			}
			criteriaTime.orOperator(criteriaApplyTime, criteriaDealTime);
		}
		
		criteria.andOperator(criteriaTime,criteriaSearch,criteriaOk);
		Query query = Query.query(criteria);
		query.with(new Sort(Sort.Direction.DESC, "applyTime"));
		long count = mongoTemplate.count(query, Cashback.class);

同时使用 andOperator,orOperator

Override
    public List<PresalesDO> queryAllPresales(PresalesRequestDO searchVO) {
        Integer pageNum = searchVO.getPageNum();
        Integer pageSize = searchVO.getPageSize();

        Criteria criteria = Criteria.where("group_id").is(searchVO.getGroupId());
        List<Criteria> criList = new ArrayList<>();
        List<Criteria> orCriList = new ArrayList<>();

        if (!EmptyUtil.isEmpty(searchVO.getHandle())){
            String handle = StrUtil.escapeExprSpecialWord(searchVO.getHandle());
            criList.add(Criteria.where("handle").regex(handle));
        }

        if(!EmptyUtil.isEmpty(searchVO.getBeginTime())){
            criList.add(Criteria.where("create_time").gte(searchVO.getBeginTime()));
        }
        if(!EmptyUtil.isEmpty(searchVO.getEndTime())){
            criList.add(Criteria.where("create_time").lte(searchVO.getEndTime()));
        }


        if (!EmptyUtil.isEmpty(searchVO.getUserName())){
            String userName = StrUtil.escapeExprSpecialWord(searchVO.getUserName());
            criList.add(Criteria.where("user_name").regex(userName));
        }

        if (!EmptyUtil.isEmpty(searchVO.getPhoneNumber())){
            String phoneNumber = StrUtil.escapeExprSpecialWord(searchVO.getPhoneNumber());
            criList.add(Criteria.where("phone_number").regex(phoneNumber));
        }

        if (!EmptyUtil.isEmpty(searchVO.getHandler())){
            String hander = StrUtil.escapeExprSpecialWord(searchVO.getHandler());
            criList.add(Criteria.where("handler").regex(hander));
        }

        if (!EmptyUtil.isEmpty(searchVO.getHandlerPhone())){
            String handlerPhone = StrUtil.escapeExprSpecialWord(searchVO.getHandlerPhone());
            criList.add(Criteria.where("handler_phone").regex(handlerPhone));
        }

        if (!EmptyUtil.isEmpty(searchVO.getState())){
            criList.add(Criteria.where("state").is(searchVO.getState()));
        }

        if (!EmptyUtil.isEmpty(searchVO.getArea())){
//            criList.add(Criteria.where("area").in(searchVO.getArea()));
            for ( String area: searchVO.getArea()) {
                String back = StrUtil.escapeExprSpecialWord(area);
                orCriList.add(Criteria.where("area").regex(back));
            }
        }


        Criteria[] criArray = new Criteria[criList.size()];
        if (!EmptyUtil.isEmpty(criList)) {
            criteria.andOperator(criList.toArray(criArray));
        }

        Criteria[] orCriArray = new Criteria[orCriList.size()];
        if (!EmptyUtil.isEmpty(orCriList)) {
            criteria.orOperator(orCriList.toArray(orCriArray));
        }

        Query query = new Query();
//设置起始数
        query.skip((pageNum - 1) * pageSize);
//设置查询条数
        query.limit(pageSize);
//设置条件
        query.addCriteria(criteria);
        query.with(new Sort(Sort.Direction.DESC, "create_time"));
        return this.find(query, MongoCollectionName.DM_PRESALES);
    }

三、实现

实现(1)

Query对象
1 创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
2 精准条件:criteria.and(“key”).is(“条件”)
模糊条件:criteria.and(“key”).regex(“条件”)
3、封装条件:query.addCriteria(criteria)
4、大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
5、Query.addCriteria(new Criteria().andOperator(gt,lt));
6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
7、排序 :query.with(new Sort(Sort.Direction.ASC, “age”). and(new Sort(Sort.Direction.DESC, “date”)))

实体类

package com.fzy.javastudy.java.day_0906.model;

import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;

import java.time.LocalDateTime;

@Data
@Document("student")
public class Student{
    private String id;
    private String username;
    private String password;
    private int age;
    private String gender;
    private LocalDateTime createTime;
}

实现

package com.fzy.javastudy.java.day_0906.service;

import com.fzy.javastudy.java.day_0906.model.*;
import com.fzy.javastudy.spring.apimodel.*;
import com.fzy.javastudy.spring.config.ServiceException;
import com.fzy.javastudy.spring.config.SystemException;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.regex.Pattern;

/**
 * https://blog.csdn.net/sinat_35821285/article/details/83511203
 */
@Slf4j
@Service
public class MongoService {

    @Resource
    private MongoTemplate mongoTemplate;

    /**
     * 查询全部
     *
     * @return ApiResponse
     */
    public ApiResponse findStudents() {
        mongoTemplate.dropCollection(Customer.class);
        List<Student> students = mongoTemplate.findAll(Student.class);
        System.out.println(students);
        long count = mongoTemplate.count(new Query().with(new Sort(Sort.Direction.ASC, "username")), Student.class);
        return Api.ok(students, String.format("%s%d%s", "查询到", count, "条"));
    }

    /**
     * 根据id查询
     *
     * @param id _id
     * @return ApiResponse
     */
    public ApiResponse findStudentByID(String id) {
        Student student = mongoTemplate.findById(id, Student.class);
        return Api.ok(student);
    }

    /**
     * 准确查询
     *
     * @param student Student对象
     * @return ApiResponse
     */
    public ApiResponse findStudentListByMany(Student student) {
        Query query = new Query(Criteria
                .where("username").is(student.getUsername())
                .and("gender").is(student.getGender())
                .and("age").gt(student.getAge()));
        List<Student> students = mongoTemplate.find(query, Student.class);
        return Api.ok(students);
    }

    /**
     * 模糊查询
     * 模糊查询以 【^】开始 以【$】结束 【.*】相当于Mysql中的%
     *
     * @param username 用户名
     * @return ApiResponse
     */
    public ApiResponse findStudentsLikeName(String username) {
        String regex = String.format("%s%s%s", "^.*", username, ".*$");
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Query query = new Query(Criteria.where("username").regex(pattern));
        List<Student> students = mongoTemplate.find(query, Student.class);
        return Api.ok(students);
    }

    /**
     * 分页查询
     *
     * @param request
     * @return
     */
    public PageApiResponse findStudentsPage(StudentRequest request) {
        try {
            Query query = new Query();
            if (StringUtils.isNotEmpty(request.getUsername())) {
                String regex = String.format("%s%s%s", "^.*", request.getUsername(), ".*$");
                Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
                query.addCriteria(Criteria.where("username").regex(pattern));
            }
            int totalCount = (int) mongoTemplate.count(query, Student.class);
            List<Student> studentList = mongoTemplate.find(query.skip(request.getOffset()).limit(request.getPageSize()), Student.class);
            PageApiResponse response = PageApi.ok(studentList, totalCount, "获取列表成功");
            response.setTotalPage(PageCounter.toTalPage(totalCount, request.getPageSize()));
            response.handleRequest(request);
            return response;
        } catch (Exception e) {
            throw new SystemException(-1, "获取分页数据出错");
        }
    }

    /**
     * 修改
     *
     * @param student Student
     * @return ApiResponse
     */
    public ApiResponse updateStudent(Student student) {
        try {
            Query query = new Query(Criteria.where("_id").is(student.getId()));
            Update update = new Update();
            update.set("username", student.getUsername());
            update.set("password", student.getPassword());
            update.set("age", student.getAge());
            update.set("gender", student.getGender());
            UpdateResult result = mongoTemplate.upsert(query, update, Student.class);
            long count = result.getModifiedCount();
            if (count > 0) {
                return Api.ok(null, "更新成功");
            }
            throw new ServiceException(-1, "更新失败");
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new SystemException(-1, "更新出错");
        }
    }

    /**
     * 删除
     *
     * @param id id
     * @return ApiResponse
     */
    public ApiResponse delete(String id) {
        try {
            Query query = new Query(Criteria.where("_id").is(id));
            DeleteResult result = mongoTemplate.remove(query, Student.class);
            long count = result.getDeletedCount();
            if (count > 0) {
                return Api.ok(count, "删除成功");
            }
            throw new ServiceException(-1, String.format("【%s】%s", id, "不存在"));
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            throw new SystemException(-1, "删除出错");
        }
    }

    /**
     * 新增
     *
     * @param student
     * @return
     */
    public ApiResponse createStudent(Student student) {
        try {
            Student insert = mongoTemplate.insert(student);
            return Api.ok(insert);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SystemException(-1, "创建出错");
        }
    }
}

实现(2)

package com.adc.da.base.dao;

import com.adc.da.util.constant.Constant;
import com.adc.da.util.utils.StringUtils;
import com.adc.da.util.utils.UUID;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import org.bson.types.Decimal128;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.DocumentCallbackHandler;
import org.springframework.data.mongodb.core.IndexOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.index.CompoundIndexDefinition;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;


@Service
public class BaseMongoDB {
    /**
     * MongoTemplate
     */
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 创建索引
     * 只包含单键和复合索引
     *
     * @param collectionName 集合名称
     * @param fieldName      字段名称
     */
    public void ensureIndex(String collectionName, String... fieldName) {
        IndexOperations indexOperations = mongoTemplate.indexOps(collectionName);
        Index index = null;
        if (fieldName.length == 1) {
            index = new Index();
            index.on(fieldName[0], Sort.Direction.DESC);
        } else {
            BasicDBObject dbObject = new BasicDBObject();
            for (String aFieldName : fieldName) {
                //复合索引 1dec -1asc
                dbObject.put(aFieldName, 1);
            }
            index = new CompoundIndexDefinition(dbObject);
        }
        indexOperations.ensureIndex(index);
    }

    /**
     * 增加一条数据
     *
     * @param tableName
     * @param params
     * @return
     */
    public Map<String, Object> save(String tableName, Map<String, Object> params) {
        BasicDBObject val = new BasicDBObject(params);
        val.put(Constant.SORT_NAME, new Date());
        mongoTemplate.insert(val, tableName);
        id2Id(val);
        return val.toMap();
    }

    /**
     * insertDBObjectList
     *
     * @param tableName
     * @param dbObjects
     */
    public void insertDBObjectList(String tableName, List<DBObject> dbObjects) {
        mongoTemplate.insert(dbObjects, tableName);
        Update update = new Update();
        update.currentDate(Constant.SORT_NAME);
        mongoTemplate.updateMulti(new Query(), update, tableName);
    }

    /**
     * findShowFields
     *
     * @param tableName
     * @param query
     * @param fields
     * @param skip
     * @param limit
     * @return
     */
    public DBCursor findShowFields(String tableName, DBObject query, DBObject fields, int skip, int limit) {
        DBCursor resultList = mongoTemplate.getCollection(tableName).find(query, fields).skip(skip).limit(limit);
        return resultList;
    }

    /**
     * 批量删除
     *
     * @param tableName
     * @param ids
     */
    public void deleteByIds(String tableName, String... ids) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").in(convertObjectId(ids)));
        mongoTemplate.remove(query, tableName);
    }

    /**
     * deleteByQuery
     *
     * @param tableName
     * @param query
     */
    public void deleteByQuery(String tableName, Query query) {
        mongoTemplate.remove(query, tableName);
    }

    /**
     * 清除表数据
     *
     * @param tableName
     */
    public void deleteAll(String tableName) {
        Query query = new Query();
        mongoTemplate.remove(query, tableName);
    }

    /**
     * 更新一条数据
     *
     * @param query
     * @param update
     * @param tableName
     */
    public void updateFirst(Query query, Update update, String tableName) {
        mongoTemplate.updateFirst(query, update, tableName);
    }

    /**
     * 更新n条数据
     *
     * @param query
     * @param update
     * @param tableName
     */
    public void updateMulti(Query query, Update update, String tableName) {
        mongoTemplate.updateMulti(query, update, tableName);
    }

    /**
     * 获取表中数据量
     *
     * @param tableName
     * @return
     */
    public long count(String tableName) {
        return mongoTemplate.count(null, tableName);
    }

    /**
     * 获取表中数据量
     *
     * @param query
     * @param tableName
     * @return
     */
    public long count(Query query, String tableName) {
        return mongoTemplate.count(query, tableName);
    }

    /**
     * 获取数据列表
     *
     * @param query
     * @param tableName
     * @return
     */
    public List<DBObject> getResultList(Query query, String tableName, int skip, int limit) {
        List<DBObject> list = new ArrayList<>();
        mongoTemplate.executeQuery(query.skip(skip).limit(limit), tableName, new DocumentCallbackHandler() {
            @Override
            public void processDocument(DBObject dbObject) throws MongoException, DataAccessException {
                id2Id(dbObject);
                toChangeBigDecimal(dbObject);
                list.add(dbObject);
            }
        });
        return list;
    }

    /**
     * getCount
     *
     * @param tableName
     * @param query
     * @param criteria
     * @return
     */
    public long getCount(String tableName, DBObject query, Criteria criteria) {
        BasicQuery basicQuery = new BasicQuery(query);
        Query queryAll = basicQuery.addCriteria(criteria);
        return mongoTemplate.count(queryAll, tableName);
    }

    /**
     * getCount
     *
     * @param tableName
     * @param query
     * @return
     */
    public long getCount(String tableName, DBObject query) {
        Query queryTemp = new Query();
        generatorLikeQuery(query.toMap(), queryTemp);
        return mongoTemplate.count(queryTemp, tableName);
    }

    /**
     * getList
     *
     * @param tableName
     * @param query
     * @param skip
     * @param limit
     * @return
     */
    public List<DBObject> getList(String tableName, Query query, int skip, int limit) {
        query.skip(skip);
        query.addCriteria(Criteria.where("_id").ne(null));
        query.limit(limit);
        return mongoTemplate.find(query, DBObject.class, tableName);
    }

    /**
     * getList
     *
     * @param tableName
     * @param query
     * @param skip
     * @param limit
     * @return
     */
    public List<DBObject> getList(String tableName, DBObject query, int skip, int limit) {
        List<DBObject> list = new ArrayList<>();
        DBCursor dbCursor = mongoTemplate.getCollection(tableName).find(query);
        dbCursor.skip(skip);
        dbCursor.limit(limit);
        while (dbCursor.hasNext()) {
            addList(list, dbCursor);
        }
        dbCursor.close();
        return list;
    }

    /**
     * 用于特殊查询比如模糊查询
     *
     * @param tableName
     * @param query
     * @return
     */
    public LinkedList<DBObject> getList(String tableName, Query query) {
        LinkedList<DBObject> list = new LinkedList<>();

        mongoTemplate.executeQuery(query, tableName, dbObject -> {
//            toChangeBigDecimal(dbObject);
//            id2Id(dbObject);
            list.add(dbObject);
        });
        return list;
    }

    /**
     * addList
     *
     * @param list
     * @param dbCursor
     */
    private void addList(List list, DBCursor dbCursor) {
        DBObject next = dbCursor.next();
        ObjectId id = (ObjectId) next.get("_id");
        next.put("_id", id.toString());
        list.add(next);
    }

    /**
     * 转换为ObjectId
     *
     * @param ids
     * @return
     */
    public ObjectId[] convertObjectId(String... ids) {
        if (ids == null) {
            return new ObjectId[0];
        }
        ObjectId[] objectIds = new ObjectId[ids.length];

        if (ids == null || ids.length == 0) {
            return objectIds;
        }

        for (int i = 0; i < ids.length; i++) {
            objectIds[i] = new ObjectId(ids[i]);
        }
        return objectIds;
    }

    /**
     * 整理dbObject(转化ObjectId为String)
     *
     * @param dbObject
     */
    public void id2Id(DBObject dbObject) {
        ObjectId objectId = (ObjectId) dbObject.get("_id");
        dbObject.put("_id", objectId.toString());
    }

    /**
     * setPageable
     *
     * @param pageNum
     * @param pageSize
     * @param sort
     * @return
     */
    public Pageable setPageable(int pageNum, int pageSize, Sort sort) {
        Pageable pageable = new PageRequest(pageNum, pageSize, sort);
        return pageable;
    }

    /**
     * existTable
     *
     * @param table
     * @return
     */
    public boolean existTable(String table) {
        return mongoTemplate.collectionExists(table);
    }

    /**
     * @Author: xiaoyu
     * @Date: 15:37 2017/12/13
     * @Description: tableName ==> collectionName paramsMap==>查询键值对
     * @param: [tableName, paramsMap]
     * @return: java.util.List<com.mongodb.DBObject>
     * @ModifyBy:
     */
    public List<DBObject> findParamsMap(String tableName, DBObject dbObject) {
        DBCursor dbObjects = mongoTemplate.execute(tableName, dbCollection -> dbCollection.find(dbObject));
        List<DBObject> dbObjectList = new ArrayList<>();
        dbObjects.forEach(dbObject1 -> {
            final ObjectId id = (ObjectId) dbObject1.get("_id");
            dbObject1.put("_id", id.toString());
            dbObjectList.add(dbObject1);
        });
        return dbObjectList;
    }

    /**
     * 根据Query查询结果集
     *
     * @param tableName
     * @param query
     * @return
     */
    public List<DBObject> findByQuery(String tableName, Query query) {
        List<DBObject> returnList = new ArrayList<>();
        mongoTemplate.executeQuery(query, tableName, dbObject -> {
            toChangeBigDecimal(dbObject);
            returnList.add(dbObject);
        });
        return returnList;
    }

    /**
     * 根据Query查询结果集
     *
     * @param tableName
     * @param query
     * @return
     */
    public List<DBObject> findByAggregate(String tableName, Query query) {
        List<DBObject> returnList = new ArrayList<>();
        mongoTemplate.executeQuery(query, tableName, dbObject -> {
            if (dbObject.get("_id") instanceof LinkedHashMap) {
                for (Object id : ((LinkedHashMap) dbObject.get("_id")).keySet()) {
                    dbObject.put(id.toString(),((LinkedHashMap) dbObject.get("_id")).get(id));
                }
            }
            dbObject.removeField("_id");
            toChangeBigDecimal(dbObject);
            returnList.add(dbObject);
        });
        return returnList;
    }


    /**
     * 删除字段
     *
     * @param dbObject
     * @param field
     * @return
     */
    public DBObject removeField(DBObject dbObject, String field) {
        Set<String> set = dbObject.keySet();
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String fieldInDb = iterator.next();
            if (field.equals(fieldInDb)) {
                iterator.remove();
            }
        }
        return dbObject;
    }

    /**
     * id查询
     *
     * @param tableName
     * @param id
     * @return
     */
    public DBObject getPartsMsg(String tableName, String id) {
        ObjectId objectId = new ObjectId(id);
        DBObject dbObject = mongoTemplate.execute(tableName, dbCollection -> dbCollection.findOne(objectId));
        return dbObject;
    }

    /**
     * 根据配件id获取配件信息
     *
     * @param tableName
     * @param ids
     * @return
     */
    public List<DBObject> queryByIds(String tableName, String... ids) {
        List<DBObject> returnValue = new ArrayList<>();
        Query query = new Query();
        if (ids.length == 0) {
            return null;
        }
        query.addCriteria(Criteria.where("_id").in(ids));
        mongoTemplate.executeQuery(query, tableName, dbObject -> {
            returnValue.add(dbObject);
        });
        return returnValue;
    }

    /**
     * 清除全部
     * 慎用
     */
    public void clearCollections(String tableName) {
        mongoTemplate.dropCollection(tableName);
    }

    /**
     * 保存ListMap
     *
     * @param tableName
     * @param params
     */
    public void saveAll(String tableName, List<LinkedHashMap<String, Object>> params) {
        int size = params.size();
        if (size >= 50000) {
            double i = size / 10000.0;
            int j = 0;
            for (; j < ((int) i); j++) {
                mongoTemplate.insert(mapToDBObject(params.subList(j * 10000, (j + 1) * 10000)), tableName);
            }
            mongoTemplate.insert(mapToDBObject(params.subList(j * 10000, (int) (j * 10000 + (i - j) * 10000))),
                tableName);
        } else {
            mongoTemplate.insert(mapToDBObject(params), tableName);
        }
    }

    /**
     * 映射关系
     *
     * @return
     * @author 作者信息
     * date 2018-08-27
     **/
    private List<DBObject> mapToDBObject(List<LinkedHashMap<String, Object>> params) {
        List<DBObject> dbObjects = new ArrayList<>();
        params.forEach(map -> {
            dbObjects.add(new BasicDBObject(map));
        });
        return dbObjects;
    }

    /**
     * 保存ListMap
     *
     * @param tableName
     * @param params
     */
    public void backUp(String tableName, JSONArray params) {
        List<DBObject> dbObjects = new ArrayList();
        for (int i = 0; i < params.size(); i++) {
            JSONObject jsonObject = params.getJSONObject(i);
            DBObject dbObject = new BasicDBObject(jsonObject);
            Object id = dbObject.get("_id");
            ObjectId objectId = new ObjectId(id.toString());
            ((BasicDBObject) dbObject).put("_id", objectId);
            ((BasicDBObject) dbObject).append(Constant.SORT_NAME, new Date());
            dbObjects.add(dbObject);
        }
        mongoTemplate.insert(dbObjects, tableName);
    }

    /**
     * @return
     */
    public List<DBObject> pageMongo(Criteria criteria, String tableName,
                                    Map<String, Object> paramFind, Integer pageNo, Integer pageSize) {
        List<DBObject> returnList = new ArrayList<>();
        Query query = new Query();
        generatorLikeQuery(paramFind, query);
        query.skip(pageNo);
        query.limit(pageSize);
        Sort.Direction desc = Sort.Direction.DESC;
        Sort sort = new Sort(desc, Constant.SORT_NAME);
        query.with(sort);
        if (criteria != null) {
            query.addCriteria(criteria);
        }
        mongoTemplate.executeQuery(query, tableName, dbObject -> {
            toChangeBigDecimal(dbObject);
            id2Id(dbObject);
            returnList.add(dbObject);
        });
        return returnList;
    }

    /**
     * toChangeBigDecimal
     *
     * @param dbObject
     */
    private void toChangeBigDecimal(DBObject dbObject) {
        Set<String> keys = dbObject.keySet();
        for (String key : keys) {
            Object value = dbObject.get(key);
            if (value instanceof Decimal128) {
                value = ((Decimal128) value).bigDecimalValue().toPlainString();
            }
            dbObject.put(key, value);
        }
    }

    /**
     * 处理mongodb查询建立regex 模糊查询的query
     *
     * @param paramFind
     * @param query
     */
    public void generatorLikeQuery(Map<String, Object> paramFind, Query query) {
        if (paramFind != null && !paramFind.isEmpty()) {
            Iterator<String> iterator = paramFind.keySet().iterator();
            Criteria criteria = new Criteria();
            while (iterator.hasNext()) {
                String next = iterator.next();
                Object value = paramFind.get(next);
                if (value instanceof String) {
                    //_ {} $  ^
                    value = filterRegex(((String) value));
                    query.addCriteria(criteria.where("_id").ne(null)
                        .and(next).regex(Pattern.compile("^.*" + value + ".*$")));
                } else {
                    query.addCriteria(criteria.where("_id").ne(null).and(next).is(value));
                }
            }

        }
    }

    /**
     * 转义正则特殊字符 ($()*+.[]?\^{},|)
     *
     * @param keyword
     * @return
     */
    public String filterRegex(String keyword) {
        if (StringUtils.isNotBlank(keyword)) {
            String[] fbsArr = {"\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|"};
            for (String key : fbsArr) {
                if (keyword.contains(key)) {
                    keyword = keyword.replace(key, "\\" + key);
                }
            }
        }
        return keyword;
    }

    /**
     * distinctQuery
     *
     * @param collectionName
     * @param criteria
     * @param key
     * @return
     */
    public List<DBObject> distinctQuery(String collectionName, Criteria criteria, String key) {
        BasicQuery basicQuery = new BasicQuery(new BasicDBObject());
        basicQuery.addCriteria(criteria);
        DBObject queryObject = basicQuery.getQueryObject();
        List distinct = mongoTemplate.getCollection(collectionName).distinct(key, queryObject);
        List<DBObject> returnList = new ArrayList<>();
        distinct.forEach(value -> {
            BasicDBObject dbObject = new BasicDBObject();
            dbObject.put(key, value);
            returnList.add(dbObject);
        });
        return returnList;
    }


    /**
     * aggregate
     *
     * @param agg
     * @param collectionName
     * @param dbObjectClass
     * @return
     */
    public AggregationResults<DBObject> aggregate(Aggregation agg, String collectionName,
                                                  Class<DBObject> dbObjectClass) {
        return mongoTemplate.aggregate(agg, collectionName, dbObjectClass);
    }


    /**
     * 判断字段是否存在
     */
    public boolean existsField(String collectionName, String fieldName) {
        DBObject dbObject = new BasicDBObject();
        DBObject dbObjectParam = new BasicDBObject();
        ((BasicDBObject) dbObjectParam).put("$exists", true);
        ((BasicDBObject) dbObject).put(fieldName, dbObjectParam);
        int count = mongoTemplate.getCollection(collectionName).find(dbObject).count();
        return count > 0;
    }

    /**
     * 创建临时表
     */
    public String createTempCollection(String collectionName) {
        String tempName = "temp" + UUID.randomUUID(4);
        List<DBObject> allResult = mongoTemplate.find(new Query(), DBObject.class, collectionName);
        mongoTemplate.getCollection(tempName).insert(allResult);
        return tempName;
    }

    /**
     * 修改字段名称
     *
     * @param paramMap key是以前的字段名称,value是之后修改的字段名称
     */
    public void updateFields(String collectionName, Map<String, String> paramMap) {
        Update update = new Update();
        Set<String> keySet = paramMap.keySet();
        for (String key : keySet) {
            if (!existsField(collectionName, paramMap.get(key))) {
                update.rename(key, paramMap.get(key));
            }
        }
        if (!update.toString().equals("{ }")) {
            mongoTemplate.updateMulti(new Query(), update, collectionName);
        }
    }
}


引用:

https://blog.csdn.net/qq_36324685/article/details/82621156

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值