mongo分页设计和实现

眉间皱痕 提交于 2021-01-26 07:37:31

一、思路

通过链式操作和有序集合实现。

 

二、分页关键实现摘抄

/**
 * mongo操作 各项目需配置bean mongoCommonTemplate
 * 
 * @author 漂泊者及其影子
 * @date 2016年6月28日
 */
public class MongoOperator {
	private static final Logger log = LoggerFactory.getLogger(MongoOperator.class);

	protected static MongoTemplate mongoTemplate;
	static {
		init();
	}

	public static void init() {
		if (ApplicationContextHelper.containsBean("mongoCommonTemplate")) {
			mongoTemplate = (MongoTemplate) ApplicationContextHelper.getBean("mongoCommonTemplate");
			log.info("mongoTemplate初始化完毕");
		} else {
			throw new RuntimeException("请在spring中引入mongotemplate,bean名称为mongoCommonTemplate");
		}

	}

	public MongoOperator() {

	}

	public static <T> List<T> findByQuery(Query query, Class<T> clazz) {
		return mongoTemplate.find(query, clazz);
	}

	/***
	 * mongo分页查询
	 * 
	 * @param proNames
	 * @param operates
	 * @param values
	 * @param pageable
	 * @param clazz
	 * @return
	 * @date 2016年6月28日
	 */
	public static <T> Pagination<T> findByProperty(QueryProperty queryProperty, Pageable pageable, Class<T> clazz) {
		Pagination<T> pagination = new Pagination<T>();
		PaginationCondition pc = new PaginationCondition(pageable.getPageNumber(), pageable.getPageSize());
		int page = pageable.getPageNumber();
		int pageSize = pageable.getPageSize();

		Query query = new Query();

		if (CollectionUtil.isNotEmpty(queryProperty.getProNames())) {
			Criteria criteria = createCriteria(queryProperty);
			query.addCriteria(criteria);
		}
		long totalCount = mongoTemplate.count(query, clazz);
		query.skip(pc.getOffset());// skip相当于从那条记录开始
		query.limit(pc.getPageSize());// 从skip开始,取多少条记录
		Sort sort = pageable.getSort();
		if (sort != null) {
			query.with(sort);
		}
		List<T> items = mongoTemplate.find(query, clazz);
		pagination.setTotal(NumberUtils.toInt(totalCount + "", 0));
		int maxPage = 0;
		if (totalCount == 0) {
			maxPage = 0;
		} else if (totalCount <= pageSize) {
			maxPage = 1;
		} else {
			if (pageSize == 0)
				pageSize = 10;
			maxPage = NumberUtils.toInt(totalCount + "", 0) / pageSize + 1;
		}
		pagination.setMaxPage(maxPage);
		pagination.setItems(items);
		pagination.setPage(page);
		pagination.setPageSize(pageSize);
		return pagination;
	}

	public  static Criteria createCriteria(QueryProperty queryProperty) {
		LinkedList<String> proNames = queryProperty.getProNames();
		LinkedList<OperateEnum> operates = queryProperty.getOperates();
		LinkedList<Object> values = queryProperty.getValues();

		Criteria criteria = null;
		String proName = null;
		OperateEnum operate = null;
		Object value = null;

		for (int i = 0; i < proNames.size(); i++) {
			proName = proNames.get(i);
			operate = operates.get(i);
			value = values.get(i);
			if (i == 0) {
				criteria = new Criteria(proName);
			} else {
				criteria = criteria.and(proName);
			}
			switch (operate) {
			case GT:
				criteria.gt(value);
				break;
			case LT:
				criteria.lt(value);
				break;
			case GTE:
				criteria.gte(value);
				break;
			case LTE:
				criteria.lte(value);
				break;
			case EQ:
				criteria.is(value);
				break;
			case NE:
				criteria.ne(value);
				break;
			case IN:
				criteria.in(value);
				break;
			case NIN:
				criteria.nin(value);
				break;
			case NOT:
				criteria.not();
				break;
			case ALL:
				criteria.all(value);
				break;
			case REGEX:
				criteria.regex(escapeRegexString(String.valueOf(value)), "i");
				break;
			case BETWEENLONG:
				String val = String.valueOf(value);
				long from = NumberUtils.toLong(val.split(",")[0]);
				long to = NumberUtils.toLong(val.split(",")[1]);
				criteria.gte(from).lte(to);
				break;
			default:
				criteria.is(value);
				break;
			}
		}
		return criteria;
	}
	/**
	 * 把字符串中含有正则表达式特殊意义的字符转义
	 * @param value
	 * @return
	 */
	public static String escapeRegexString(String value){
		final char[] reserved={'.','$','^','{','}','[',']','(',')','|','*','+','?','\\'};
		char c;
		boolean bingo=false;
		StringBuilder sb=new StringBuilder(value);
		for(int i=0; i<sb.length(); i++){
			bingo=false;
			c=sb.charAt(i);
			for(int j=0; j<reserved.length; j++){
				if(c==reserved[j]){
					bingo=true;
					break;
				}
			}
			if(bingo){
				sb.insert(i, '\\');
				i++;
			}
		}
		return sb.toString();
	}
	/**
	 * @param proName
	 * @param operat
	 * @param value
	 * @return
	 */
	public static Criteria createCriteria(String proName, OperateEnum operat, Object value) {
		Criteria criteria = Criteria.where(proName);
		switch (operat) {
		case GT:
			criteria.gt(value);
			break;
		case LT:
			criteria.lt(value);
			break;
		case GTE:
			criteria.gte(value);
			break;
		case LTE:
			criteria.lte(value);
			break;
		case EQ:
			criteria.is(value);
			break;
		case NE:
			criteria.ne(value);
			break;
		case IN:
			if (value instanceof Collection) {
				criteria.in((Collection<?>) value);
			} else if (value.getClass().isArray()) {
				Object[] array = (Object[]) value;
				criteria.in(Arrays.asList(array));
			} else {
				criteria.in(value);
			}
			break;
		case NIN:
			if (value instanceof Collection) {
				criteria.nin((Collection<?>) value);
			} else if (value.getClass().isArray()) {
				Object[] array = (Object[]) value;
				criteria.nin(Arrays.asList(array));
			} else {
				criteria.nin(value);
			}
			break;
		case NOT:
			criteria.not();
			break;
		case ALL:
			criteria.all(value);
			break;
		case REGEX:
			criteria.regex(escapeRegexString(String.valueOf(value)), "i");
			break;
		case BETWEENLONG:
			String val = String.valueOf(value);
			long from = NumberUtils.toLong(val.split(",")[0]);
			long to = NumberUtils.toLong(val.split(",")[1]);
			criteria.gte(from).lte(to);
			break;
		default:
			criteria.is(value);
			break;
		}
		return criteria;
	}
}

操作枚举

package com.iflashbuy.base.repository.mongo;

/**
 * mongo分页查询封装
 * 
 * @author 漂泊者及其影子
 * @date 2016年6月28日
 */
public enum OperateEnum {
	GT("$gt"), LT("$lt"), GTE("$gte"), LTE("$lte"), EQ("$eq"), NE("$ne"), IN("$in"), NIN("$nin"), ALL("$all"), NOT(
			"$not"), REGEX("$lte"), BETWEENLONG("此操作mongoTemplate中没有自己封装,依照betweenlong可以类推betweenDate,betweenint等between的比较");

	private String op;

	OperateEnum(String op) {
		this.op = op;
	}

	@Override
	public String toString() {
		return op;
	}

	public String getValue() {
		return op;
	}
}

支持链式操作的QueryProperty类设计,对象里面放置容器对象,从而实现链式操作,mongoTemplate的源码中有很多类似的设计。


public class QueryProperty {
	private LinkedList<String> proNames = new LinkedList<String>();
	private LinkedList<OperateEnum> operates = new LinkedList<OperateEnum>();
	private LinkedList<Object> values = new LinkedList<Object>();

	public LinkedList<String> getProNames() {
		return proNames;
	}

	public LinkedList<OperateEnum> getOperates() {
		return operates;
	}

	public LinkedList<Object> getValues() {
		return values;
	}

	public QueryProperty addQueryProperties(String proName, OperateEnum operate, Object value) {
		if (StringUtil.isNotEmpty(proName)) {
			proNames.add(proName);
			operates.add(operate);
			values.add(value);
		}
		return this;
	}

}

 

三、调用例子

		String batchNum = codeUseParam.getBatchNum();
		int page = codeUseParam.getPage();
		int pageSize = codeUseParam.getPageSize();
		String entId = codeUseParam.getEntId();
		String remark = codeUseParam.getRemark();
		String businessId = codeUseParam.getBusinessId();
		String dateFrom = codeUseParam.getDateFrom();
		String dateTo = codeUseParam.getDateTo();	
		Pagination<ZcodeAssignInfo> pagination = new Pagination<ZcodeAssignInfo>();
		List<ZcodeAssignInfo> zcodeAssignInfos = null;


        
		QueryProperty queryProperty = new QueryProperty();
		if(StringUtil.isNotEmpty(entId)) {
			queryProperty.addQueryProperties("entId", OperateEnum.EQ, NumberUtils.toInt(entId, -1));
		}
		if(StringUtil.isNotEmpty(businessId)) {
			
			queryProperty.addQueryProperties("businessId", OperateEnum.EQ, NumberUtils.toInt(businessId, -1));
		}
		if(StringUtil.isNotEmpty(remark)) {
			queryProperty.addQueryProperties("activateRemark", OperateEnum.EQ, remark);
		}
		queryProperty.addQueryProperties("batchOrderNum", OperateEnum.EQ, batchNum);
		queryProperty.addQueryProperties("activateStatus", OperateEnum.EQ, 1);
		if (StringUtil.isNotEmpty(dateFrom) && StringUtil.isNotEmpty(dateTo)) {
			queryProperty.addQueryProperties("activateTime", OperateEnum.BETWEENLONG,DateUtil.getLongTypedTimeFromTimeStr(dateFrom + " 00:00:00", DateUtil.DATETIME_FORMAT) + ","  + DateUtil.getLongTypedTimeFromTimeStr(dateTo + " 23:59:59", DateUtil.DATETIME_FORMAT));
		} else if (StringUtil.isNotEmpty(dateFrom)) {
			queryProperty.addQueryProperties("activateTime", OperateEnum.GTE, DateUtil.getLongTypedTimeFromTimeStr(dateFrom + " 00:00:00", DateUtil.DATETIME_FORMAT));
		} else if (StringUtil.isNotEmpty(dateTo)) {
			queryProperty.addQueryProperties("activateTime", OperateEnum.LTE, DateUtil.getLongTypedTimeFromTimeStr(dateTo + " 23:59:59", DateUtil.DATETIME_FORMAT));
		}
		
		Pageable pageable  = new PageRequest(page, pageSize, new Sort(new Sort.Order(Sort.Direction.DESC, "createTime")));
		Pagination<CodeDeactive> codeDeactivatePage = MongoOperator.findByProperty(queryProperty, pageable, CodeDeactive.class);

四、亮点

1、通过mongoTemplate实现

2、关于QueryProperty容器对象的设计

3、实现between的功能

4、操作枚举的设计

5、like的实现

 

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